mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 07:03:03 +02:00
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: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> Signed-off-by: Lizhi Hou <lizhi.hou@amd.com> Link: https://lore.kernel.org/r/20250616091418.2605476-1-lizhi.hou@amd.com
This commit is contained in:
parent
98df1626ae
commit
e252e3f348
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
offset = mem->dev_addr - heap->mem.dev_addr;
|
||||
mem->userptr = heap->mem.userptr + offset;
|
||||
mem->kva = heap->mem.kva + offset;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
drm_gem_object_get(to_gobj(heap));
|
||||
|
||||
return 0;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
ret = drm_gem_shmem_pin(&abo->base);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user