summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/mmu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2017-11-01 03:56:19 +1000
committerBen Skeggs <bskeggs@redhat.com>2017-11-02 13:32:27 +1000
commitd30af7ce2c96e57b503da1d70454818331f0a6d5 (patch)
tree348c34ff605a635601515d83aab8b6ddd54c1d62 /drivers/gpu/drm/nouveau/nvkm/subdev/mmu
parentaf3b8d53869c175fce424b6bfd1f49c1b53baef1 (diff)
downloadblackbird-obmc-linux-d30af7ce2c96e57b503da1d70454818331f0a6d5.tar.gz
blackbird-obmc-linux-d30af7ce2c96e57b503da1d70454818331f0a6d5.zip
drm/nouveau/mmu: handle instance block setup
We previously required each VMM user to allocate their own page directory and fill in the instance block themselves. It makes more sense to handle this in a common location. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/mmu')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c81
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c2
5 files changed, 49 insertions, 92 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
index 9fdd1446da5f..22264d3db22f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
@@ -446,7 +446,6 @@ static void
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_memory *pgt;
u32 pde;
@@ -459,9 +458,8 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde)
pgt = vpgt->mem[big];
vpgt->mem[big] = NULL;
- list_for_each_entry(vpgd, &vm->pgd_list, head) {
- mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
- }
+ if (mmu->func->map_pgt)
+ mmu->func->map_pgt(vm, pde, vpgt->mem);
mmu->func->flush(vm);
@@ -474,7 +472,6 @@ 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;
int big = (type != mmu->func->spg_shift);
u32 pgt_size;
int ret;
@@ -487,9 +484,8 @@ nvkm_vm_map_pgt(struct nvkm_vm *vm, u32 pde, u32 type)
if (unlikely(ret))
return ret;
- list_for_each_entry(vpgd, &vm->pgd_list, head) {
- mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
- }
+ if (mmu->func->map_pgt)
+ mmu->func->map_pgt(vm, pde, vpgt->mem);
vpgt->refcount[big]++;
return 0;
@@ -592,7 +588,6 @@ nvkm_vm_legacy(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
u64 mm_length = (offset + length) - mm_offset;
int ret;
- INIT_LIST_HEAD(&vm->pgd_list);
kref_init(&vm->refcount);
vm->fpde = offset >> (mmu->func->pgt_bits + 12);
vm->lpde = (offset + length - 1) >> (mmu->func->pgt_bits + 12);
@@ -644,58 +639,10 @@ nvkm_vm_new(struct nvkm_device *device, u64 offset, u64 length, u64 mm_offset,
return -EINVAL;
}
-static int
-nvkm_vm_link(struct nvkm_vm *vm, struct nvkm_gpuobj *pgd)
-{
- struct nvkm_mmu *mmu = vm->mmu;
- struct nvkm_vm_pgd *vpgd;
- int i;
-
- if (!pgd)
- return 0;
-
- vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL);
- if (!vpgd)
- return -ENOMEM;
-
- vpgd->obj = pgd;
-
- mutex_lock(&vm->mutex);
- for (i = vm->fpde; i <= vm->lpde; i++)
- mmu->func->map_pgt(pgd, i, vm->pgt[i - vm->fpde].mem);
- list_add(&vpgd->head, &vm->pgd_list);
- mutex_unlock(&vm->mutex);
- return 0;
-}
-
-static void
-nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd)
-{
- struct nvkm_vm_pgd *vpgd, *tmp;
-
- if (!mpgd)
- return;
-
- mutex_lock(&vm->mutex);
- list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
- if (vpgd->obj == mpgd) {
- list_del(&vpgd->head);
- kfree(vpgd);
- break;
- }
- }
- mutex_unlock(&vm->mutex);
-}
-
static void
nvkm_vm_del(struct kref *kref)
{
struct nvkm_vm *vm = container_of(kref, typeof(*vm), refcount);
- struct nvkm_vm_pgd *vpgd, *tmp;
-
- list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
- nvkm_vm_unlink(vm, vpgd->obj);
- }
nvkm_mm_fini(&vm->mm);
vfree(vm->pgt);
@@ -705,20 +652,28 @@ nvkm_vm_del(struct kref *kref)
}
int
-nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_gpuobj *pgd)
+nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_memory *inst)
{
if (ref) {
- int ret = nvkm_vm_link(ref, pgd);
- if (ret)
- return ret;
+ if (ref->func->join && inst) {
+ int ret = ref->func->join(ref, inst), i;
+ if (ret)
+ return ret;
+
+ if (ref->mmu->func->map_pgt) {
+ for (i = ref->fpde; i <= ref->lpde; i++)
+ ref->mmu->func->map_pgt(ref, i, ref->pgt[i - ref->fpde].mem);
+ }
+ }
kref_get(&ref->refcount);
}
if (*ptr) {
- if ((*ptr)->bootstrapped && pgd)
+ if ((*ptr)->func->part && inst)
+ (*ptr)->func->part(*ptr, inst);
+ if ((*ptr)->bootstrapped && inst)
nvkm_memory_unref(&(*ptr)->pgt[0].mem[0]);
- nvkm_vm_unlink(*ptr, pgd);
kref_put(&(*ptr)->refcount, nvkm_vm_del);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
index 536260782cff..167c201d29e3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
@@ -70,8 +70,9 @@ const u8 gf100_pte_storage_type_map[256] =
void
-gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_memory *pgt[2])
+gf100_vm_map_pgt(struct nvkm_vmm *vmm, u32 index, struct nvkm_memory *pgt[2])
{
+ struct nvkm_memory *pgd = vmm->pd->pt[0]->memory;
u32 pde[2] = { 0, 0 };
if (pgt[0])
@@ -161,7 +162,6 @@ gf100_vm_flush(struct nvkm_vm *vm)
{
struct nvkm_mmu *mmu = vm->mmu;
struct nvkm_device *device = mmu->subdev.device;
- struct nvkm_vm_pgd *vpgd;
u32 type;
type = 0x00000001; /* PAGE_ALL */
@@ -169,24 +169,22 @@ gf100_vm_flush(struct nvkm_vm *vm)
type |= 0x00000004; /* HUB_ONLY */
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
- */
- nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x100c80) & 0x00ff0000)
- break;
- );
-
- nvkm_wr32(device, 0x100cb8, vpgd->obj->addr >> 8);
- nvkm_wr32(device, 0x100cbc, 0x80000000 | type);
-
- /* wait for flush to be queued? */
- nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x100c80) & 0x00008000)
- break;
- );
- }
+ /* looks like maybe a "free flush slots" counter, the
+ * faster you write to 0x100cbc to more it decreases
+ */
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x100c80) & 0x00ff0000)
+ break;
+ );
+
+ nvkm_wr32(device, 0x100cb8, vm->pd->pt[0]->addr >> 8);
+ nvkm_wr32(device, 0x100cbc, 0x80000000 | type);
+
+ /* wait for flush to be queued? */
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x100c80) & 0x00008000)
+ break;
+ );
mutex_unlock(&mmu->subdev.mutex);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
index ba1c04e00701..da75d1da0658 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
@@ -31,8 +31,10 @@
#include <nvif/class.h>
void
-nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2])
+nv50_vm_map_pgt(struct nvkm_vmm *vmm, u32 pde, struct nvkm_memory *pgt[2])
{
+ struct nvkm_vmm_join *join;
+ u32 pdeo = vmm->mmu->func->vmm.pd_offset + (pde * 8);
u64 phys = 0xdeadcafe00000000ULL;
u32 coverage = 0;
@@ -56,10 +58,12 @@ nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2])
phys |= 0x20;
}
- 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);
+ list_for_each_entry(join, &vmm->join, head) {
+ nvkm_kmap(join->inst);
+ nvkm_wo32(join->inst, pdeo + 0, lower_32_bits(phys));
+ nvkm_wo32(join->inst, pdeo + 4, upper_32_bits(phys));
+ nvkm_done(join->inst);
+ }
}
static inline u64
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
index f490a636e9f0..3271ec1c3c83 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
@@ -18,7 +18,7 @@ struct nvkm_mmu_func {
u8 spg_shift;
u8 lpg_shift;
- void (*map_pgt)(struct nvkm_gpuobj *pgd, u32 pde,
+ void (*map_pgt)(struct nvkm_vmm *, u32 pde,
struct nvkm_memory *pgt[2]);
void (*map)(struct nvkm_vma *, struct nvkm_memory *,
struct nvkm_mem *, u32 pte, u32 cnt,
@@ -41,7 +41,7 @@ struct nvkm_mmu_func {
extern const struct nvkm_mmu_func nv04_mmu;
-void nv50_vm_map_pgt(struct nvkm_gpuobj *, u32, struct nvkm_memory **);
+void nv50_vm_map_pgt(struct nvkm_vmm *, u32, struct nvkm_memory **);
void nv50_vm_map(struct nvkm_vma *, struct nvkm_memory *, struct nvkm_mem *,
u32, u32, u64, u64);
void nv50_vm_map_sg(struct nvkm_vma *, struct nvkm_memory *, struct nvkm_mem *,
@@ -49,7 +49,7 @@ void nv50_vm_map_sg(struct nvkm_vma *, struct nvkm_memory *, struct nvkm_mem *,
void nv50_vm_unmap(struct nvkm_vma *, struct nvkm_memory *, u32, u32);
void nv50_vm_flush(struct nvkm_vm *);
-void gf100_vm_map_pgt(struct nvkm_gpuobj *, u32, struct nvkm_memory **);
+void gf100_vm_map_pgt(struct nvkm_vmm *, u32, struct nvkm_memory **);
void gf100_vm_map(struct nvkm_vma *, struct nvkm_memory *, struct nvkm_mem *,
u32, u32, u64, u64);
void gf100_vm_map_sg(struct nvkm_vma *, struct nvkm_memory *, struct nvkm_mem *,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
index 25e86ce3d29c..7e00b9adca05 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
@@ -131,7 +131,7 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
/* ... and the GPU storage for it, except on Tesla-class GPUs that
* have the PD embedded in the instance structure.
*/
- if (desc->size && mmu->func->vmm.global) {
+ if (desc->size) {
const u32 size = pd_header + desc->size * (1 << desc->bits);
vmm->pd->pt[0] = nvkm_mmu_ptc_get(mmu, size, desc->align, true);
if (!vmm->pd->pt[0])
OpenPOWER on IntegriCloud