]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel/amdxdna: Revise device bo creation and free
authorLizhi Hou <lizhi.hou@amd.com>
Mon, 16 Jun 2025 09:14:16 +0000 (02:14 -0700)
committerLizhi Hou <lizhi.hou@amd.com>
Tue, 17 Jun 2025 05:29:09 +0000 (22:29 -0700)
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
drivers/accel/amdxdna/aie2_ctx.c
drivers/accel/amdxdna/amdxdna_gem.c
drivers/accel/amdxdna/amdxdna_gem.h

index 3e38a5f637ea049c9b8f08dc270482377a4fc4f3..f20999f2d66864fd4a6b7069e866727c37befb39 100644 (file)
@@ -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;
index 26831ec69f8950bb893e2b2a7320b27d3e2cb413..0f85a0105178844efbcfc8d1b90194252451547f 100644 (file)
 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;
 
-       return 0;
+       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);
+}
+
+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 @@ free_map:
        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 @@ mm_unlock:
 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);
 
index aee97e971d6d7d9d194323f9b91f65c960e5a503..ae29db94a9d33483f6fe708000e43f3c639dbc09 100644 (file)
@@ -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);