Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 987eec10 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau: embed nouveau_mm



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 52d07331
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -518,7 +518,7 @@ struct nouveau_pm_engine {
};

struct nouveau_vram_engine {
	struct nouveau_mm *mm;
	struct nouveau_mm mm;

	int  (*init)(struct drm_device *);
	void (*takedown)(struct drm_device *dev);
+25 −35
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
#include "nouveau_mm.h"

static inline void
region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a)
{
	list_del(&a->nl_entry);
	list_del(&a->fl_entry);
@@ -35,7 +35,7 @@ region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a)
}

static struct nouveau_mm_node *
region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
{
	struct nouveau_mm_node *b;

@@ -57,33 +57,33 @@ region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size)
	return b;
}

#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \
#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \
	list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry)

void
nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this)
nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this)
{
	struct nouveau_mm_node *prev = node(this, prev);
	struct nouveau_mm_node *next = node(this, next);

	list_add(&this->fl_entry, &rmm->free);
	list_add(&this->fl_entry, &mm->free);
	this->type = 0;

	if (prev && prev->type == 0) {
		prev->length += this->length;
		region_put(rmm, this);
		region_put(mm, this);
		this = prev;
	}

	if (next && next->type == 0) {
		next->offset  = this->offset;
		next->length += this->length;
		region_put(rmm, this);
		region_put(mm, this);
	}
}

int
nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc,
	       u32 align, struct nouveau_mm_node **pnode)
{
	struct nouveau_mm_node *prev, *this, *next;
@@ -92,17 +92,17 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
	u32 splitoff;
	u32 s, e;

	list_for_each_entry(this, &rmm->free, fl_entry) {
	list_for_each_entry(this, &mm->free, fl_entry) {
		e = this->offset + this->length;
		s = this->offset;

		prev = node(this, prev);
		if (prev && prev->type != type)
			s = roundup(s, rmm->block_size);
			s = roundup(s, mm->block_size);

		next = node(this, next);
		if (next && next->type != type)
			e = rounddown(e, rmm->block_size);
			e = rounddown(e, mm->block_size);

		s  = (s + align_mask) & ~align_mask;
		e &= ~align_mask;
@@ -110,10 +110,10 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
			continue;

		splitoff = s - this->offset;
		if (splitoff && !region_split(rmm, this, splitoff))
		if (splitoff && !region_split(mm, this, splitoff))
			return -ENOMEM;

		this = region_split(rmm, this, min(size, e - s));
		this = region_split(mm, this, min(size, e - s));
		if (!this)
			return -ENOMEM;

@@ -127,9 +127,8 @@ nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc,
}

int
nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
{
	struct nouveau_mm *rmm;
	struct nouveau_mm_node *heap;

	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
@@ -138,32 +137,25 @@ nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block)
	heap->offset = roundup(offset, block);
	heap->length = rounddown(offset + length, block) - heap->offset;

	rmm = kzalloc(sizeof(*rmm), GFP_KERNEL);
	if (!rmm) {
		kfree(heap);
		return -ENOMEM;
	}
	rmm->block_size = block;
	mutex_init(&rmm->mutex);
	INIT_LIST_HEAD(&rmm->nodes);
	INIT_LIST_HEAD(&rmm->free);
	list_add(&heap->nl_entry, &rmm->nodes);
	list_add(&heap->fl_entry, &rmm->free);

	*prmm = rmm;
	mutex_init(&mm->mutex);
	mm->block_size = block;
	INIT_LIST_HEAD(&mm->nodes);
	INIT_LIST_HEAD(&mm->free);

	list_add(&heap->nl_entry, &mm->nodes);
	list_add(&heap->fl_entry, &mm->free);
	return 0;
}

int
nouveau_mm_fini(struct nouveau_mm **prmm)
nouveau_mm_fini(struct nouveau_mm *mm)
{
	struct nouveau_mm *rmm = *prmm;
	struct nouveau_mm_node *node, *heap =
		list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry);
		list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry);

	if (!list_is_singular(&rmm->nodes)) {
	if (!list_is_singular(&mm->nodes)) {
		printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
		list_for_each_entry(node, &rmm->nodes, nl_entry) {
		list_for_each_entry(node, &mm->nodes, nl_entry) {
			printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
			       node->type, node->offset, node->length);
		}
@@ -172,7 +164,5 @@ nouveau_mm_fini(struct nouveau_mm **prmm)
	}

	kfree(heap);
	kfree(rmm);
	*prmm = NULL;
	return 0;
}
+2 −2
Original line number Diff line number Diff line
@@ -44,8 +44,8 @@ struct nouveau_mm {
	u32 block_size;
};

int  nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block);
int  nouveau_mm_fini(struct nouveau_mm **);
int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
int  nouveau_mm_fini(struct nouveau_mm *);
int  nouveau_mm_pre(struct nouveau_mm *);
int  nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc,
		    u32 align, struct nouveau_mm_node **);
+19 −19
Original line number Diff line number Diff line
@@ -172,9 +172,9 @@ nouveau_vm_unmap_pgt(struct nouveau_vm *vm, int big, u32 fpde, u32 lpde)
			vm->map_pgt(vpgd->obj, pde, vpgt->obj);
		}

		mutex_unlock(&vm->mm->mutex);
		mutex_unlock(&vm->mm.mutex);
		nouveau_gpuobj_ref(NULL, &pgt);
		mutex_lock(&vm->mm->mutex);
		mutex_lock(&vm->mm.mutex);
	}
}

@@ -191,18 +191,18 @@ nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type)
	pgt_size  = (1 << (vm->pgt_bits + 12)) >> type;
	pgt_size *= 8;

	mutex_unlock(&vm->mm->mutex);
	mutex_unlock(&vm->mm.mutex);
	ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000,
				 NVOBJ_FLAG_ZERO_ALLOC, &pgt);
	mutex_lock(&vm->mm->mutex);
	mutex_lock(&vm->mm.mutex);
	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(&vm->mm->mutex);
		mutex_unlock(&vm->mm.mutex);
		nouveau_gpuobj_ref(NULL, &pgt);
		mutex_lock(&vm->mm->mutex);
		mutex_lock(&vm->mm.mutex);
		return 0;
	}

@@ -223,10 +223,10 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
	u32 fpde, lpde, pde;
	int ret;

	mutex_lock(&vm->mm->mutex);
	ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node);
	mutex_lock(&vm->mm.mutex);
	ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node);
	if (unlikely(ret != 0)) {
		mutex_unlock(&vm->mm->mutex);
		mutex_unlock(&vm->mm.mutex);
		return ret;
	}

@@ -245,13 +245,13 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
		if (ret) {
			if (pde != fpde)
				nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1);
			nouveau_mm_put(vm->mm, vma->node);
			mutex_unlock(&vm->mm->mutex);
			nouveau_mm_put(&vm->mm, vma->node);
			mutex_unlock(&vm->mm.mutex);
			vma->node = NULL;
			return ret;
		}
	}
	mutex_unlock(&vm->mm->mutex);
	mutex_unlock(&vm->mm.mutex);

	vma->vm     = vm;
	vma->offset = (u64)vma->node->offset << 12;
@@ -270,11 +270,11 @@ nouveau_vm_put(struct nouveau_vma *vma)
	fpde = (vma->node->offset >> vm->pgt_bits);
	lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits;

	mutex_lock(&vm->mm->mutex);
	mutex_lock(&vm->mm.mutex);
	nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde);
	nouveau_mm_put(vm->mm, vma->node);
	nouveau_mm_put(&vm->mm, vma->node);
	vma->node = NULL;
	mutex_unlock(&vm->mm->mutex);
	mutex_unlock(&vm->mm.mutex);
}

int
@@ -360,11 +360,11 @@ nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd)

	nouveau_gpuobj_ref(pgd, &vpgd->obj);

	mutex_lock(&vm->mm->mutex);
	mutex_lock(&vm->mm.mutex);
	for (i = vm->fpde; i <= vm->lpde; i++)
		vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj);
	list_add(&vpgd->head, &vm->pgd_list);
	mutex_unlock(&vm->mm->mutex);
	mutex_unlock(&vm->mm.mutex);
	return 0;
}

@@ -377,7 +377,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
	if (!mpgd)
		return;

	mutex_lock(&vm->mm->mutex);
	mutex_lock(&vm->mm.mutex);
	list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
		if (vpgd->obj == mpgd) {
			pgd = vpgd->obj;
@@ -386,7 +386,7 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
			break;
		}
	}
	mutex_unlock(&vm->mm->mutex);
	mutex_unlock(&vm->mm.mutex);

	nouveau_gpuobj_ref(NULL, &pgd);
}
+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ struct nouveau_vma {

struct nouveau_vm {
	struct drm_device *dev;
	struct nouveau_mm *mm;
	struct nouveau_mm mm;
	int refcount;

	struct list_head pgd_list;
Loading