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

Commit fd2871af authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau: initial changes to support multiple VMAs per buffer object



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a3fcd0a9
Loading
Loading
Loading
Loading
+72 −26
Original line number Original line Diff line number Diff line
@@ -49,10 +49,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
		DRM_ERROR("bo %p still attached to GEM object\n", bo);
		DRM_ERROR("bo %p still attached to GEM object\n", bo);


	nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
	nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
	if (nvbo->vma.node) {
	nouveau_bo_vma_del(nvbo, &nvbo->vma);
		nouveau_vm_unmap(&nvbo->vma);
		nouveau_vm_put(&nvbo->vma);
	}
	kfree(nvbo);
	kfree(nvbo);
}
}


@@ -103,6 +100,7 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
		return -ENOMEM;
		return -ENOMEM;
	INIT_LIST_HEAD(&nvbo->head);
	INIT_LIST_HEAD(&nvbo->head);
	INIT_LIST_HEAD(&nvbo->entry);
	INIT_LIST_HEAD(&nvbo->entry);
	INIT_LIST_HEAD(&nvbo->vma_list);
	nvbo->tile_mode = tile_mode;
	nvbo->tile_mode = tile_mode;
	nvbo->tile_flags = tile_flags;
	nvbo->tile_flags = tile_flags;
	nvbo->bo.bdev = &dev_priv->ttm.bdev;
	nvbo->bo.bdev = &dev_priv->ttm.bdev;
@@ -114,24 +112,22 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
	}
	}


	nouveau_bo_fixup_align(nvbo, flags, &align, &size);
	nouveau_bo_fixup_align(nvbo, flags, &align, &size);
	align >>= PAGE_SHIFT;
	nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
	nouveau_bo_placement_set(nvbo, flags, 0);


	if (dev_priv->chan_vm) {
	if (dev_priv->chan_vm) {
		ret = nouveau_vm_get(dev_priv->chan_vm, size, nvbo->page_shift,
		ret = nouveau_bo_vma_add(nvbo, dev_priv->chan_vm, &nvbo->vma);
				     NV_MEM_ACCESS_RW, &nvbo->vma);
		if (ret) {
		if (ret) {
			kfree(nvbo);
			kfree(nvbo);
			return ret;
			return ret;
		}
		}
	}
	}


	nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
	nouveau_bo_placement_set(nvbo, flags, 0);

	nvbo->channel = chan;
	nvbo->channel = chan;
	ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
	ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
			  ttm_bo_type_device, &nvbo->placement, align, 0,
			  ttm_bo_type_device, &nvbo->placement,
			  false, NULL, size, nouveau_bo_del_ttm);
			  align >> PAGE_SHIFT, 0, false, NULL, size,
			  nouveau_bo_del_ttm);
	if (ret) {
	if (ret) {
		/* ttm will call nouveau_bo_del_ttm if it fails.. */
		/* ttm will call nouveau_bo_del_ttm if it fails.. */
		return ret;
		return ret;
@@ -818,20 +814,20 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
{
{
	struct nouveau_mem *node = new_mem->mm_node;
	struct nouveau_mem *node = new_mem->mm_node;
	struct nouveau_bo *nvbo = nouveau_bo(bo);
	struct nouveau_bo *nvbo = nouveau_bo(bo);
	struct nouveau_vma *vma = &nvbo->vma;
	struct nouveau_vma *vma;

	if (!vma->vm)
		return;


	list_for_each_entry(vma, &nvbo->vma_list, head) {
		if (new_mem->mem_type == TTM_PL_VRAM) {
		if (new_mem->mem_type == TTM_PL_VRAM) {
		nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
			nouveau_vm_map(vma, new_mem->mm_node);
		} else
		} else
		if (new_mem->mem_type == TTM_PL_TT &&
		if (new_mem->mem_type == TTM_PL_TT &&
	    nvbo->page_shift == nvbo->vma.vm->spg_shift) {
		    nvbo->page_shift == vma->vm->spg_shift) {
		nouveau_vm_map_sg(&nvbo->vma, 0, new_mem->
			nouveau_vm_map_sg(vma, 0, new_mem->
				  num_pages << PAGE_SHIFT, node, node->pages);
					  num_pages << PAGE_SHIFT,
					  node, node->pages);
		} else {
		} else {
		nouveau_vm_unmap(&nvbo->vma);
			nouveau_vm_unmap(vma);
		}
	}
	}
}
}


@@ -1077,3 +1073,53 @@ struct ttm_bo_driver nouveau_bo_driver = {
	.io_mem_free = &nouveau_ttm_io_mem_free,
	.io_mem_free = &nouveau_ttm_io_mem_free,
};
};


struct nouveau_vma *
nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nouveau_vm *vm)
{
	struct nouveau_vma *vma;
	list_for_each_entry(vma, &nvbo->vma_list, head) {
		if (vma->vm == vm)
			return vma;
	}

	return NULL;
}

int
nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
		   struct nouveau_vma *vma)
{
	const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
	struct nouveau_mem *node = nvbo->bo.mem.mm_node;
	int ret;

	ret = nouveau_vm_get(vm, size, nvbo->page_shift,
			     NV_MEM_ACCESS_RW, vma);
	if (ret)
		return ret;

	if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
		nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
	else
	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
		nouveau_vm_map_sg(vma, 0, size, node, node->pages);

	list_add_tail(&vma->head, &nvbo->vma_list);
	return 0;
}

void
nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
{
	if (vma->node) {
		if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) {
			spin_lock(&nvbo->bo.bdev->fence_lock);
			ttm_bo_wait(&nvbo->bo, false, false, false);
			spin_unlock(&nvbo->bo.bdev->fence_lock);
			nouveau_vm_unmap(vma);
		}

		nouveau_vm_put(vma);
		list_del(&vma->head);
	}
}
+7 −0
Original line number Original line Diff line number Diff line
@@ -116,6 +116,7 @@ struct nouveau_bo {
	struct nouveau_channel *channel;
	struct nouveau_channel *channel;


	struct nouveau_vma vma;
	struct nouveau_vma vma;
	struct list_head vma_list;
	unsigned page_shift;
	unsigned page_shift;


	uint32_t tile_mode;
	uint32_t tile_mode;
@@ -1283,6 +1284,12 @@ extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *);
extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
			       bool no_wait_reserve, bool no_wait_gpu);
			       bool no_wait_reserve, bool no_wait_gpu);


extern struct nouveau_vma *
nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *);
extern int  nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
			       struct nouveau_vma *);
extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);

/* nouveau_fence.c */
/* nouveau_fence.c */
struct nouveau_fence;
struct nouveau_fence;
extern int nouveau_fence_init(struct drm_device *);
extern int nouveau_fence_init(struct drm_device *);
+1 −0
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ struct nouveau_vm_pgd {
};
};


struct nouveau_vma {
struct nouveau_vma {
	struct list_head head;
	struct nouveau_vm *vm;
	struct nouveau_vm *vm;
	struct nouveau_mm_node *node;
	struct nouveau_mm_node *node;
	u64 offset;
	u64 offset;