Commit e252e3f3 authored by Lizhi Hou's avatar Lizhi Hou
Browse files

accel/amdxdna: Revise device bo creation and free



The device bo is allocated from the device heap memory. (a trunk of
memory dedicated to device)

Rename amdxdna_gem_insert_node_locked to amdxdna_gem_heap_alloc
and move related sanity checks into it.

Add amdxdna_gem_dev_obj_free and move device bo free code into it.

Calculate the kernel virtual address of device bo by the device
heap memory address and offset.

Reviewed-by: default avatarJacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Signed-off-by: default avatarLizhi Hou <lizhi.hou@amd.com>
Link: https://lore.kernel.org/r/20250616091418.2605476-1-lizhi.hou@amd.com
parent 98df1626
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -566,7 +566,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
			.size = MAX_CHAIN_CMDBUF_SIZE,
		};

		abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp, true);
		abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp);
		if (IS_ERR(abo)) {
			ret = PTR_ERR(abo);
			goto free_cmd_bufs;
+104 −89
Original line number Diff line number Diff line
@@ -24,40 +24,79 @@
MODULE_IMPORT_NS("DMA_BUF");

static int
amdxdna_gem_insert_node_locked(struct amdxdna_gem_obj *abo, bool use_vmap)
amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
{
	struct amdxdna_client *client = abo->client;
	struct amdxdna_dev *xdna = client->xdna;
	struct amdxdna_mem *mem = &abo->mem;
	struct amdxdna_gem_obj *heap;
	u64 offset;
	u32 align;
	int ret;

	mutex_lock(&client->mm_lock);

	heap = client->dev_heap;
	if (!heap) {
		ret = -EINVAL;
		goto unlock_out;
	}

	if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) {
		XDNA_ERR(xdna, "Invalid dev heap userptr");
		ret = -EINVAL;
		goto unlock_out;
	}

	if (mem->size == 0 || mem->size > heap->mem.size) {
		XDNA_ERR(xdna, "Invalid dev bo size 0x%lx, limit 0x%lx",
			 mem->size, heap->mem.size);
		ret = -EINVAL;
		goto unlock_out;
	}

	align = 1 << max(PAGE_SHIFT, xdna->dev_info->dev_mem_buf_shift);
	ret = drm_mm_insert_node_generic(&abo->dev_heap->mm, &abo->mm_node,
	ret = drm_mm_insert_node_generic(&heap->mm, &abo->mm_node,
					 mem->size, align,
					 0, DRM_MM_INSERT_BEST);
	if (ret) {
		XDNA_ERR(xdna, "Failed to alloc dev bo memory, ret %d", ret);
		return ret;
		goto unlock_out;
	}

	mem->dev_addr = abo->mm_node.start;
	offset = mem->dev_addr - abo->dev_heap->mem.dev_addr;
	mem->userptr = abo->dev_heap->mem.userptr + offset;
	mem->pages = &abo->dev_heap->base.pages[offset >> PAGE_SHIFT];
	mem->nr_pages = mem->size >> PAGE_SHIFT;

	if (use_vmap) {
		mem->kva = vmap(mem->pages, mem->nr_pages, VM_MAP, PAGE_KERNEL);
		if (!mem->kva) {
			XDNA_ERR(xdna, "Failed to vmap");
			drm_mm_remove_node(&abo->mm_node);
			return -EFAULT;
	offset = mem->dev_addr - heap->mem.dev_addr;
	mem->userptr = heap->mem.userptr + offset;
	mem->kva = heap->mem.kva + offset;

	drm_gem_object_get(to_gobj(heap));

unlock_out:
	mutex_unlock(&client->mm_lock);

	return ret;
}

static void
amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
{
	mutex_destroy(&abo->lock);
	kfree(abo);
}

	return 0;
static void
amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo)
{
	struct amdxdna_gem_obj *heap;

	mutex_lock(&abo->client->mm_lock);

	drm_mm_remove_node(&abo->mm_node);

	heap = abo->client->dev_heap;
	drm_gem_object_put(to_gobj(heap));

	mutex_unlock(&abo->client->mm_lock);
}

static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
@@ -213,6 +252,20 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
	return ret;
}

static void amdxdna_gem_dev_obj_free(struct drm_gem_object *gobj)
{
	struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev);
	struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);

	XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, abo->mem.dev_addr);
	if (abo->pinned)
		amdxdna_gem_unpin(abo);

	amdxdna_gem_heap_free(abo);
	drm_gem_object_release(gobj);
	amdxdna_gem_destroy_obj(abo);
}

static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
				struct vm_area_struct *vma)
{
@@ -374,19 +427,6 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
	if (abo->pinned)
		amdxdna_gem_unpin(abo);

	if (abo->type == AMDXDNA_BO_DEV) {
		mutex_lock(&abo->client->mm_lock);
		drm_mm_remove_node(&abo->mm_node);
		mutex_unlock(&abo->client->mm_lock);

		vunmap(abo->mem.kva);
		drm_gem_object_put(to_gobj(abo->dev_heap));
		drm_gem_object_release(gobj);
		mutex_destroy(&abo->lock);
		kfree(abo);
		return;
	}

	if (abo->type == AMDXDNA_BO_DEV_HEAP)
		drm_mm_takedown(&abo->mm);

@@ -402,7 +442,7 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
}

static const struct drm_gem_object_funcs amdxdna_gem_dev_obj_funcs = {
	.free = amdxdna_gem_obj_free,
	.free = amdxdna_gem_dev_obj_free,
};

static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
@@ -527,6 +567,7 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev,
			    struct drm_file *filp)
{
	struct amdxdna_client *client = filp->driver_priv;
	struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
	struct amdxdna_dev *xdna = to_xdna_dev(dev);
	struct drm_gem_shmem_object *shmem;
	struct amdxdna_gem_obj *abo;
@@ -553,18 +594,26 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev,

	shmem->map_wc = false;
	abo = to_xdna_obj(&shmem->base);

	abo->type = AMDXDNA_BO_DEV_HEAP;
	abo->client = client;
	abo->mem.dev_addr = client->xdna->dev_info->dev_mem_base;
	drm_mm_init(&abo->mm, abo->mem.dev_addr, abo->mem.size);

	ret = drm_gem_vmap(to_gobj(abo), &map);
	if (ret) {
		XDNA_ERR(xdna, "Vmap heap bo failed, ret %d", ret);
		goto release_obj;
	}
	abo->mem.kva = map.vaddr;

	client->dev_heap = abo;
	drm_gem_object_get(to_gobj(abo));
	mutex_unlock(&client->mm_lock);

	return abo;

release_obj:
	drm_gem_object_put(to_gobj(abo));
mm_unlock:
	mutex_unlock(&client->mm_lock);
	return ERR_PTR(ret);
@@ -573,58 +622,32 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev,
struct amdxdna_gem_obj *
amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
			 struct amdxdna_drm_create_bo *args,
			 struct drm_file *filp, bool use_vmap)
			 struct drm_file *filp)
{
	struct amdxdna_client *client = filp->driver_priv;
	struct amdxdna_dev *xdna = to_xdna_dev(dev);
	size_t aligned_sz = PAGE_ALIGN(args->size);
	struct amdxdna_gem_obj *abo, *heap;
	struct amdxdna_gem_obj *abo;
	int ret;

	mutex_lock(&client->mm_lock);
	heap = client->dev_heap;
	if (!heap) {
		ret = -EINVAL;
		goto mm_unlock;
	}

	if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) {
		XDNA_ERR(xdna, "Invalid dev heap userptr");
		ret = -EINVAL;
		goto mm_unlock;
	}

	if (args->size > heap->mem.size) {
		XDNA_ERR(xdna, "Invalid dev bo size 0x%llx, limit 0x%lx",
			 args->size, heap->mem.size);
		ret = -EINVAL;
		goto mm_unlock;
	}

	abo = amdxdna_gem_create_obj(&xdna->ddev, aligned_sz);
	if (IS_ERR(abo)) {
		ret = PTR_ERR(abo);
		goto mm_unlock;
	}
	if (IS_ERR(abo))
		return abo;

	to_gobj(abo)->funcs = &amdxdna_gem_dev_obj_funcs;
	abo->type = AMDXDNA_BO_DEV;
	abo->client = client;
	abo->dev_heap = heap;
	ret = amdxdna_gem_insert_node_locked(abo, use_vmap);

	ret = amdxdna_gem_heap_alloc(abo);
	if (ret) {
		XDNA_ERR(xdna, "Failed to alloc dev bo memory, ret %d", ret);
		goto mm_unlock;
		amdxdna_gem_destroy_obj(abo);
		return ERR_PTR(ret);
	}

	drm_gem_object_get(to_gobj(heap));
	drm_gem_private_object_init(&xdna->ddev, to_gobj(abo), aligned_sz);

	mutex_unlock(&client->mm_lock);
	return abo;

mm_unlock:
	mutex_unlock(&client->mm_lock);
	return ERR_PTR(ret);
}

static struct amdxdna_gem_obj *
@@ -632,10 +655,10 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
			  struct amdxdna_drm_create_bo *args,
			  struct drm_file *filp)
{
	struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
	struct amdxdna_dev *xdna = to_xdna_dev(dev);
	struct drm_gem_shmem_object *shmem;
	struct amdxdna_gem_obj *abo;
	struct iosys_map map;
	int ret;

	if (args->size > XDNA_MAX_CMD_BO_SIZE) {
@@ -692,7 +715,7 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f
		abo = amdxdna_drm_create_dev_heap(dev, args, filp);
		break;
	case AMDXDNA_BO_DEV:
		abo = amdxdna_drm_alloc_dev_bo(dev, args, filp, false);
		abo = amdxdna_drm_alloc_dev_bo(dev, args, filp);
		break;
	case AMDXDNA_BO_CMD:
		abo = amdxdna_drm_create_cmd_bo(dev, args, filp);
@@ -724,20 +747,13 @@ int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo)
	struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
	int ret;

	if (abo->type == AMDXDNA_BO_DEV)
		abo = abo->client->dev_heap;

	if (is_import_bo(abo))
		return 0;

	switch (abo->type) {
	case AMDXDNA_BO_SHMEM:
	case AMDXDNA_BO_DEV_HEAP:
	ret = drm_gem_shmem_pin(&abo->base);
		break;
	case AMDXDNA_BO_DEV:
		ret = drm_gem_shmem_pin(&abo->dev_heap->base);
		break;
	default:
		ret = -EOPNOTSUPP;
	}

	XDNA_DBG(xdna, "BO type %d ret %d", abo->type, ret);
	return ret;
@@ -747,9 +763,6 @@ int amdxdna_gem_pin(struct amdxdna_gem_obj *abo)
{
	int ret;

	if (abo->type == AMDXDNA_BO_DEV)
		abo = abo->dev_heap;

	mutex_lock(&abo->lock);
	ret = amdxdna_gem_pin_nolock(abo);
	mutex_unlock(&abo->lock);
@@ -759,12 +772,12 @@ int amdxdna_gem_pin(struct amdxdna_gem_obj *abo)

void amdxdna_gem_unpin(struct amdxdna_gem_obj *abo)
{
	if (abo->type == AMDXDNA_BO_DEV)
		abo = abo->client->dev_heap;

	if (is_import_bo(abo))
		return;

	if (abo->type == AMDXDNA_BO_DEV)
		abo = abo->dev_heap;

	mutex_lock(&abo->lock);
	drm_gem_shmem_unpin(&abo->base);
	mutex_unlock(&abo->lock);
@@ -855,10 +868,12 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,

	if (is_import_bo(abo))
		drm_clflush_sg(abo->base.sgt);
	else if (abo->type == AMDXDNA_BO_DEV)
		drm_clflush_pages(abo->mem.pages, abo->mem.nr_pages);
	else
	else if (abo->mem.kva)
		drm_clflush_virt_range(abo->mem.kva + args->offset, args->size);
	else if (abo->base.pages)
		drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT);
	else
		drm_WARN(&xdna->ddev, 1, "Can not get flush memory");

	amdxdna_gem_unpin(abo);

+1 −2
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ struct amdxdna_gem_obj {

	/* Below members is uninitialized when needed */
	struct drm_mm			mm; /* For AMDXDNA_BO_DEV_HEAP */
	struct amdxdna_gem_obj		*dev_heap; /* For AMDXDNA_BO_DEV */
	struct drm_mm_node		mm_node; /* For AMDXDNA_BO_DEV */
	u32				assigned_hwctx;
	struct dma_buf			*dma_buf;
@@ -72,7 +71,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf);
struct amdxdna_gem_obj *
amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
			 struct amdxdna_drm_create_bo *args,
			 struct drm_file *filp, bool use_vmap);
			 struct drm_file *filp);

int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo);
int amdxdna_gem_pin(struct amdxdna_gem_obj *abo);