* [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval
@ 2026-03-20 21:06 Lizhi Hou
2026-03-20 21:46 ` Mario Limonciello (AMD) (kernel.org)
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Lizhi Hou @ 2026-03-20 21:06 UTC (permalink / raw)
To: ogabbay, quic_jhugo, dri-devel, mario.limonciello,
maciej.falkowski
Cc: Max Zhen, linux-kernel, sonal.santan
From: Max Zhen <max.zhen@amd.com>
Refactor amdxdna GEM buffer object (BO) handling to simplify address
management and unify BO type semantics.
Introduce helper APIs to retrieve commonly used BO addresses:
- User virtual address (UVA)
- Kernel virtual address (KVA)
- Device address (IOVA/PA)
These helpers centralize address lookup logic and avoid duplicating
BO-specific handling across submission and execution paths. This also
improves readability and reduces the risk of inconsistent address
handling in future changes.
As part of the refactor:
- Rename SHMEM BO type to SHARE to better reflect its usage.
- Merge CMD BO handling into SHARE, removing special-case logic for
command buffers.
- Consolidate BO type handling paths to reduce code duplication and
simplify maintenance.
No functional change is intended. The refactor prepares the driver for
future enhancements by providing a cleaner abstraction for BO address
management.
Signed-off-by: Max Zhen <max.zhen@amd.com>
---
drivers/accel/amdxdna/aie2_ctx.c | 8 +-
drivers/accel/amdxdna/aie2_message.c | 33 +-
drivers/accel/amdxdna/amdxdna_ctx.c | 23 +-
drivers/accel/amdxdna/amdxdna_ctx.h | 15 +-
drivers/accel/amdxdna/amdxdna_gem.c | 400 +++++++++++-------------
drivers/accel/amdxdna/amdxdna_gem.h | 32 +-
drivers/accel/amdxdna/amdxdna_pci_drv.c | 2 +-
drivers/accel/amdxdna/amdxdna_ubuf.c | 17 +-
drivers/accel/amdxdna/amdxdna_ubuf.h | 5 -
include/uapi/drm/amdxdna_accel.h | 9 +-
10 files changed, 266 insertions(+), 278 deletions(-)
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 6292349868c5..66dbbfd322a2 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -79,7 +79,7 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
}
ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
- amdxdna_obj_dma_addr(hwctx->client, heap),
+ amdxdna_obj_dma_addr(heap),
heap->mem.size);
if (ret) {
XDNA_ERR(xdna, "Map host buf failed, ret %d", ret);
@@ -659,14 +659,14 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
.size = MAX_CHAIN_CMDBUF_SIZE,
};
- abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp);
+ abo = amdxdna_drm_create_dev_bo(&xdna->ddev, &args, client->filp);
if (IS_ERR(abo)) {
ret = PTR_ERR(abo);
goto free_cmd_bufs;
}
XDNA_DBG(xdna, "Command buf %d addr 0x%llx size 0x%lx",
- i, abo->mem.dev_addr, abo->mem.size);
+ i, amdxdna_gem_dev_addr(abo), abo->mem.size);
priv->cmd_buf[i] = abo;
}
@@ -707,7 +707,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
}
ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
- amdxdna_obj_dma_addr(hwctx->client, heap),
+ amdxdna_obj_dma_addr(heap),
heap->mem.size);
if (ret) {
XDNA_ERR(xdna, "Map host buffer failed, ret %d", ret);
diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c
index 4ec591306854..6e3fb52aa35f 100644
--- a/drivers/accel/amdxdna/aie2_message.c
+++ b/drivers/accel/amdxdna/aie2_message.c
@@ -548,10 +548,10 @@ int aie2_config_cu(struct amdxdna_hwctx *hwctx,
}
req.cfgs[i] = FIELD_PREP(AIE2_MSG_CFG_CU_PDI_ADDR,
- abo->mem.dev_addr >> shift);
+ amdxdna_gem_dev_addr(abo) >> shift);
req.cfgs[i] |= FIELD_PREP(AIE2_MSG_CFG_CU_FUNC, cu->cu_func);
XDNA_DBG(xdna, "CU %d full addr 0x%llx, cfg 0x%x", i,
- abo->mem.dev_addr, req.cfgs[i]);
+ amdxdna_gem_dev_addr(abo), req.cfgs[i]);
drm_gem_object_put(gobj);
}
req.num_cus = hwctx->cus->num_cus;
@@ -998,6 +998,7 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
struct mailbox_channel *chann = hwctx->priv->mbox_chann;
struct amdxdna_client *client = hwctx->client;
struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
+ void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_cmd_chain *payload;
struct xdna_mailbox_msg msg;
@@ -1009,6 +1010,9 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
u32 op;
u32 i;
+ if (!cmd_buf)
+ return -ENOMEM;
+
op = amdxdna_cmd_get_op(cmd_abo);
payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len);
if (op != ERT_CMD_CHAIN) {
@@ -1032,15 +1036,14 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
u32 boh = (u32)(payload->data[i]);
struct amdxdna_gem_obj *abo;
- abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_CMD);
+ abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_SHMEM);
if (!abo) {
XDNA_ERR(xdna, "Failed to find cmd BO %d", boh);
return -ENOENT;
}
size = cmdbuf_abo->mem.size - offset;
- ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva + offset,
- abo, &size, &op);
+ ret = aie2_cmdlist_fill_slot(cmd_buf + offset, abo, &size, &op);
amdxdna_gem_put_obj(abo);
if (ret)
return ret;
@@ -1050,16 +1053,16 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
XDNA_DBG(xdna, "Total %d commands:", ccnt);
print_hex_dump_debug("cmdbufs: ", DUMP_PREFIX_OFFSET, 16, 4,
- cmdbuf_abo->mem.kva, offset, false);
+ cmd_buf, offset, false);
msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
if (msg.opcode == MSG_OP_MAX_OPCODE)
return -EOPNOTSUPP;
/* The offset is the accumulated total size of the cmd buffer */
- EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr,
+ EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo),
offset, ccnt);
- drm_clflush_virt_range(cmdbuf_abo->mem.kva, offset);
+ drm_clflush_virt_range(cmd_buf, offset);
msg.handle = job;
msg.notify_cb = notify_cb;
@@ -1084,27 +1087,29 @@ int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx,
struct mailbox_channel *chann = hwctx->priv->mbox_chann;
struct amdxdna_dev *xdna = hwctx->client->xdna;
struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
+ void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
struct xdna_mailbox_msg msg;
union exec_chain_req req;
u32 op = ERT_INVALID_CMD;
size_t size;
int ret;
+ if (!cmd_buf)
+ return -ENOMEM;
+
size = cmdbuf_abo->mem.size;
- ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva, cmd_abo, &size, &op);
+ ret = aie2_cmdlist_fill_slot(cmd_buf, cmd_abo, &size, &op);
if (ret)
return ret;
- print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4,
- cmdbuf_abo->mem.kva, size, false);
+ print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4, cmd_buf, size, false);
msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
if (msg.opcode == MSG_OP_MAX_OPCODE)
return -EOPNOTSUPP;
- EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr,
- size, 1);
- drm_clflush_virt_range(cmdbuf_abo->mem.kva, size);
+ EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo), size, 1);
+ drm_clflush_virt_range(cmd_buf, size);
msg.handle = job;
msg.notify_cb = notify_cb;
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c
index 4b921715176d..94e5639adc64 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.c
+++ b/drivers/accel/amdxdna/amdxdna_ctx.c
@@ -94,9 +94,12 @@ int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg,
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
{
- struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
u32 num_masks, count;
+ if (!cmd)
+ return NULL;
+
if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
num_masks = 0;
else
@@ -118,10 +121,13 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo)
{
- struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
u32 num_masks, i;
u32 *cu_mask;
+ if (!cmd)
+ return INVALID_CU_IDX;
+
if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
return INVALID_CU_IDX;
@@ -141,19 +147,24 @@ int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
void *err_data, size_t size)
{
struct amdxdna_client *client = job->hwctx->client;
- struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
struct amdxdna_cmd_chain *cc = NULL;
+ if (!cmd)
+ return -ENOMEM;
+
cmd->header &= ~AMDXDNA_CMD_STATE;
cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) {
cc = amdxdna_cmd_get_payload(abo, NULL);
cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0;
- abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD);
+ abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_SHMEM);
if (!abo)
return -EINVAL;
- cmd = abo->mem.kva;
+ cmd = amdxdna_gem_vmap(abo);
+ if (!cmd)
+ return -ENOMEM;
}
memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd));
@@ -472,7 +483,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
job->drv_cmd = drv_cmd;
if (cmd_bo_hdl != AMDXDNA_INVALID_BO_HANDLE) {
- job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl, AMDXDNA_BO_CMD);
+ job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl, AMDXDNA_BO_SHMEM);
if (!job->cmd_bo) {
XDNA_ERR(xdna, "Failed to get cmd bo from %d", cmd_bo_hdl);
ret = -EINVAL;
diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h
index 57db1527a93b..a8557d7e8923 100644
--- a/drivers/accel/amdxdna/amdxdna_ctx.h
+++ b/drivers/accel/amdxdna/amdxdna_ctx.h
@@ -158,7 +158,10 @@ struct amdxdna_sched_job {
static inline u32
amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
{
- struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
+
+ if (!cmd)
+ return ERT_INVALID_CMD;
return FIELD_GET(AMDXDNA_CMD_OPCODE, cmd->header);
}
@@ -166,7 +169,10 @@ amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
static inline void
amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum ert_cmd_state s)
{
- struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
+
+ if (!cmd)
+ return;
cmd->header &= ~AMDXDNA_CMD_STATE;
cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, s);
@@ -175,7 +181,10 @@ amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum ert_cmd_state s)
static inline enum ert_cmd_state
amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo)
{
- struct amdxdna_cmd *cmd = abo->mem.kva;
+ struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
+
+ if (!cmd)
+ return ERT_CMD_STATE_INVALID;
return FIELD_GET(AMDXDNA_CMD_STATE, cmd->header);
}
diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
index d80cf164740c..3c15d06b6048 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -30,7 +30,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_mem *mem = &abo->mem;
struct amdxdna_gem_obj *heap;
- u64 offset;
u32 align;
int ret;
@@ -42,7 +41,7 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
goto unlock_out;
}
- if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) {
+ if (amdxdna_gem_uva(heap) == AMDXDNA_INVALID_ADDR) {
XDNA_ERR(xdna, "Invalid dev heap userptr");
ret = -EINVAL;
goto unlock_out;
@@ -64,11 +63,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
goto unlock_out;
}
- mem->dev_addr = abo->mm_node.start;
- 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:
@@ -77,13 +71,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
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)
{
@@ -99,6 +86,105 @@ amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo)
mutex_unlock(&abo->client->mm_lock);
}
+static struct amdxdna_gem_obj *
+amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
+{
+ struct amdxdna_gem_obj *abo;
+
+ abo = kzalloc_obj(*abo);
+ if (!abo)
+ return ERR_PTR(-ENOMEM);
+
+ abo->pinned = false;
+ abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
+ mutex_init(&abo->lock);
+
+ abo->mem.dma_addr = AMDXDNA_INVALID_ADDR;
+ abo->mem.uva = AMDXDNA_INVALID_ADDR;
+ abo->mem.size = size;
+ INIT_LIST_HEAD(&abo->mem.umap_list);
+
+ return abo;
+}
+
+static void
+amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
+{
+ mutex_destroy(&abo->lock);
+ kfree(abo);
+}
+
+/*
+ * Obtains a kernel virtual address on the BO (usually of small size).
+ * The mapping is established on the first call and stays valid until
+ * amdxdna_gem_vunmap() is called.
+ */
+void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
+{
+ struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
+ int ret;
+
+ if (abo->mem.kva)
+ return abo->mem.kva;
+
+ /* The first call to get the kva, taking slow path. */
+ guard(mutex)(&abo->lock);
+
+ if (!abo->mem.kva) {
+ ret = drm_gem_vmap(to_gobj(abo), &map);
+ if (ret)
+ XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
+ else
+ abo->mem.kva = map.vaddr;
+ }
+ return abo->mem.kva;
+}
+
+/*
+ * Free mapping established through amdxdna_gem_vmap()
+ */
+static void amdxdna_gem_vunmap(struct amdxdna_gem_obj *abo)
+{
+ guard(mutex)(&abo->lock);
+
+ if (abo->mem.kva) {
+ struct iosys_map map = IOSYS_MAP_INIT_VADDR(abo->mem.kva);
+
+ drm_gem_vunmap(to_gobj(abo), &map);
+ abo->mem.kva = NULL;
+ }
+}
+
+/*
+ * Obtain the user virtual address for accessing the BO.
+ * It can be used for device to access the BO when PASID is enabled.
+ */
+u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo)
+{
+ if (abo->type == AMDXDNA_BO_DEV) {
+ struct amdxdna_gem_obj *heap = abo->client->dev_heap;
+ u64 off = amdxdna_dev_bo_offset(abo);
+
+ if (amdxdna_gem_uva(heap) != AMDXDNA_INVALID_ADDR)
+ return amdxdna_gem_uva(heap) + off;
+ return AMDXDNA_INVALID_ADDR;
+ }
+
+ return abo->mem.uva;
+}
+
+/*
+ * Obtain the address for device to access the BO.
+ */
+u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo)
+{
+ if (abo->type == AMDXDNA_BO_DEV_HEAP)
+ return abo->client->xdna->dev_info->dev_mem_base;
+ if (abo->type == AMDXDNA_BO_DEV)
+ return abo->mm_node.start;
+ return amdxdna_obj_dma_addr(abo);
+}
+
static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
const struct mmu_notifier_range *range,
unsigned long cur_seq)
@@ -161,16 +247,19 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
static void amdxdna_umap_release(struct kref *ref)
{
struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
+ struct amdxdna_gem_obj *abo = mapp->abo;
struct vm_area_struct *vma = mapp->vma;
struct amdxdna_dev *xdna;
mmu_interval_notifier_remove(&mapp->notifier);
- if (is_import_bo(mapp->abo) && vma->vm_file && vma->vm_file->f_mapping)
+ if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
mapping_clear_unevictable(vma->vm_file->f_mapping);
xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
down_write(&xdna->notifier_lock);
list_del(&mapp->node);
+ if (list_empty(&abo->mem.umap_list))
+ abo->mem.uva = AMDXDNA_INVALID_ADDR;
up_write(&xdna->notifier_lock);
kvfree(mapp->range.hmm_pfns);
@@ -232,13 +321,13 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
mapp->abo = abo;
kref_init(&mapp->refcnt);
- if (abo->mem.userptr == AMDXDNA_INVALID_ADDR)
- abo->mem.userptr = addr;
INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
mapping_set_unevictable(vma->vm_file->f_mapping);
down_write(&xdna->notifier_lock);
+ if (list_empty(&abo->mem.umap_list))
+ abo->mem.uva = addr;
list_add_tail(&mapp->node, &abo->mem.umap_list);
up_write(&xdna->notifier_lock);
@@ -256,10 +345,11 @@ 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);
+ XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, amdxdna_gem_dev_addr(abo));
if (abo->pinned)
amdxdna_gem_unpin(abo);
+ amdxdna_gem_vunmap(abo);
amdxdna_gem_heap_free(abo);
drm_gem_object_release(gobj);
amdxdna_gem_destroy_obj(abo);
@@ -390,35 +480,6 @@ static const struct dma_buf_ops amdxdna_dmabuf_ops = {
.vunmap = drm_gem_dmabuf_vunmap,
};
-static int amdxdna_gem_obj_vmap(struct amdxdna_gem_obj *abo, void **vaddr)
-{
- struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
- int ret;
-
- if (is_import_bo(abo))
- ret = dma_buf_vmap_unlocked(abo->dma_buf, &map);
- else
- ret = drm_gem_vmap(to_gobj(abo), &map);
-
- *vaddr = map.vaddr;
- return ret;
-}
-
-static void amdxdna_gem_obj_vunmap(struct amdxdna_gem_obj *abo)
-{
- struct iosys_map map;
-
- if (!abo->mem.kva)
- return;
-
- iosys_map_set_vaddr(&map, abo->mem.kva);
-
- if (is_import_bo(abo))
- dma_buf_vunmap_unlocked(abo->dma_buf, &map);
- else
- drm_gem_vunmap(to_gobj(abo), &map);
-}
-
static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags)
{
struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
@@ -452,7 +513,7 @@ static void amdxdna_gem_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);
+ XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, amdxdna_gem_dev_addr(abo));
amdxdna_hmm_unregister(abo, NULL);
flush_workqueue(xdna->notifier_wq);
@@ -463,15 +524,16 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
if (abo->type == AMDXDNA_BO_DEV_HEAP)
drm_mm_takedown(&abo->mm);
- amdxdna_gem_obj_vunmap(abo);
+ if (amdxdna_iova_on(xdna))
+ amdxdna_iommu_unmap_bo(xdna, abo);
+
+ amdxdna_gem_vunmap(abo);
mutex_destroy(&abo->lock);
- if (is_import_bo(abo)) {
+ if (is_import_bo(abo))
amdxdna_imported_obj_free(abo);
- return;
- }
-
- drm_gem_shmem_free(&abo->base);
+ else
+ drm_gem_shmem_free(&abo->base);
}
static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *filp)
@@ -481,43 +543,38 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi
int ret;
guard(mutex)(&abo->lock);
- if (abo->ref) {
- abo->ref++;
- return 0;
- }
+ if (!abo->client)
+ abo->client = filp->driver_priv;
if (amdxdna_iova_on(xdna)) {
ret = amdxdna_iommu_map_bo(xdna, abo);
if (ret)
return ret;
}
- abo->ref++;
return 0;
}
-static void amdxdna_gem_obj_close(struct drm_gem_object *gobj, struct drm_file *filp)
+static int amdxdna_gem_dev_obj_vmap(struct drm_gem_object *obj, struct iosys_map *map)
{
- struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev);
- struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
+ struct amdxdna_gem_obj *abo = to_xdna_obj(obj);
+ void *base = amdxdna_gem_vmap(abo->client->dev_heap);
+ u64 offset = amdxdna_dev_bo_offset(abo);
- guard(mutex)(&abo->lock);
- abo->ref--;
- if (abo->ref)
- return;
-
- if (amdxdna_iova_on(xdna))
- amdxdna_iommu_unmap_bo(xdna, abo);
+ if (!base)
+ return -ENOMEM;
+ iosys_map_set_vaddr(map, base + offset);
+ return 0;
}
static const struct drm_gem_object_funcs amdxdna_gem_dev_obj_funcs = {
.free = amdxdna_gem_dev_obj_free,
+ .vmap = amdxdna_gem_dev_obj_vmap,
};
static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
.free = amdxdna_gem_obj_free,
.open = amdxdna_gem_obj_open,
- .close = amdxdna_gem_obj_close,
.print_info = drm_gem_shmem_object_print_info,
.pin = drm_gem_shmem_object_pin,
.unpin = drm_gem_shmem_object_unpin,
@@ -529,31 +586,9 @@ static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
.export = amdxdna_gem_prime_export,
};
-static struct amdxdna_gem_obj *
-amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
-{
- struct amdxdna_gem_obj *abo;
-
- abo = kzalloc_obj(*abo);
- if (!abo)
- return ERR_PTR(-ENOMEM);
-
- abo->pinned = false;
- abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
- mutex_init(&abo->lock);
-
- abo->mem.userptr = AMDXDNA_INVALID_ADDR;
- abo->mem.dev_addr = AMDXDNA_INVALID_ADDR;
- abo->mem.dma_addr = AMDXDNA_INVALID_ADDR;
- abo->mem.size = size;
- INIT_LIST_HEAD(&abo->mem.umap_list);
-
- return abo;
-}
-
/* For drm_driver->gem_create_object callback */
struct drm_gem_object *
-amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
+amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size)
{
struct amdxdna_gem_obj *abo;
@@ -567,8 +602,9 @@ amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
}
static struct amdxdna_gem_obj *
-amdxdna_gem_create_shmem_object(struct drm_device *dev, size_t size)
+amdxdna_gem_create_shmem_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args)
{
+ size_t size = args->size;
struct drm_gem_shmem_object *shmem = drm_gem_shmem_create(dev, size);
if (IS_ERR(shmem))
@@ -582,7 +618,6 @@ static struct amdxdna_gem_obj *
amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args)
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
- enum amdxdna_ubuf_flag flags = 0;
struct amdxdna_drm_va_tbl va_tbl;
struct drm_gem_object *gobj;
struct dma_buf *dma_buf;
@@ -593,10 +628,7 @@ amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create
}
if (va_tbl.num_entries) {
- if (args->type == AMDXDNA_BO_CMD)
- flags |= AMDXDNA_UBUF_FLAG_MAP_DMA;
-
- dma_buf = amdxdna_get_ubuf(dev, flags, va_tbl.num_entries,
+ dma_buf = amdxdna_get_ubuf(dev, va_tbl.num_entries,
u64_to_user_ptr(args->vaddr + sizeof(va_tbl)));
} else {
dma_buf = dma_buf_get(va_tbl.dmabuf_fd);
@@ -616,18 +648,6 @@ amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create
return to_xdna_obj(gobj);
}
-static struct amdxdna_gem_obj *
-amdxdna_gem_create_object(struct drm_device *dev,
- struct amdxdna_drm_create_bo *args)
-{
- size_t aligned_sz = PAGE_ALIGN(args->size);
-
- if (args->vaddr)
- return amdxdna_gem_create_ubuf_object(dev, args);
-
- return amdxdna_gem_create_shmem_object(dev, aligned_sz);
-}
-
struct drm_gem_object *
amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
{
@@ -660,7 +680,8 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
abo = to_xdna_obj(gobj);
abo->attach = attach;
abo->dma_buf = dma_buf;
- abo->type = AMDXDNA_BO_SHMEM;
+ abo->type = AMDXDNA_BO_SHARE;
+ gobj->resv = dma_buf->resv;
return gobj;
@@ -675,92 +696,92 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
}
static struct amdxdna_gem_obj *
-amdxdna_drm_alloc_shmem(struct drm_device *dev,
- struct amdxdna_drm_create_bo *args,
- struct drm_file *filp)
+amdxdna_drm_create_share_bo(struct drm_device *dev,
+ struct amdxdna_drm_create_bo *args, struct drm_file *filp)
{
- struct amdxdna_client *client = filp->driver_priv;
struct amdxdna_gem_obj *abo;
- abo = amdxdna_gem_create_object(dev, args);
+ if (args->vaddr)
+ abo = amdxdna_gem_create_ubuf_object(dev, args);
+ else
+ abo = amdxdna_gem_create_shmem_object(dev, args);
if (IS_ERR(abo))
return ERR_CAST(abo);
- abo->client = client;
- abo->type = AMDXDNA_BO_SHMEM;
+ if (args->type == AMDXDNA_BO_DEV_HEAP)
+ abo->type = AMDXDNA_BO_DEV_HEAP;
+ else
+ abo->type = AMDXDNA_BO_SHARE;
return abo;
}
static struct amdxdna_gem_obj *
-amdxdna_drm_create_dev_heap(struct drm_device *dev,
- struct amdxdna_drm_create_bo *args,
- struct drm_file *filp)
+amdxdna_drm_create_dev_heap_bo(struct drm_device *dev,
+ struct amdxdna_drm_create_bo *args, struct drm_file *filp)
{
struct amdxdna_client *client = filp->driver_priv;
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_gem_obj *abo;
int ret;
- if (args->size > xdna->dev_info->dev_mem_size) {
- XDNA_DBG(xdna, "Invalid dev heap size 0x%llx, limit 0x%lx",
+ WARN_ON(!is_power_of_2(xdna->dev_info->dev_mem_size));
+ XDNA_DBG(xdna, "Requested dev heap size 0x%llx", args->size);
+ if (!args->size || !IS_ALIGNED(args->size, xdna->dev_info->dev_mem_size)) {
+ XDNA_ERR(xdna, "The dev heap size 0x%llx is not multiple of 0x%lx",
args->size, xdna->dev_info->dev_mem_size);
return ERR_PTR(-EINVAL);
}
+ /* HEAP BO is a special case of SHMEM BO. */
+ abo = amdxdna_drm_create_share_bo(dev, args, filp);
+ if (IS_ERR(abo))
+ return ERR_CAST(abo);
+
+ /* Set up heap for this client. */
mutex_lock(&client->mm_lock);
+
if (client->dev_heap) {
XDNA_DBG(client->xdna, "dev heap is already created");
ret = -EBUSY;
goto mm_unlock;
}
-
- abo = amdxdna_gem_create_object(dev, args);
- if (IS_ERR(abo)) {
- ret = PTR_ERR(abo);
- goto mm_unlock;
- }
-
- 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 = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
- if (ret) {
- XDNA_ERR(xdna, "Vmap heap bo failed, ret %d", ret);
- goto release_obj;
- }
-
client->dev_heap = abo;
drm_gem_object_get(to_gobj(abo));
+
+ drm_mm_init(&abo->mm, xdna->dev_info->dev_mem_base, abo->mem.size);
+
mutex_unlock(&client->mm_lock);
return abo;
-release_obj:
- drm_gem_object_put(to_gobj(abo));
mm_unlock:
mutex_unlock(&client->mm_lock);
+ drm_gem_object_put(to_gobj(abo));
return ERR_PTR(ret);
}
struct amdxdna_gem_obj *
-amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
- struct amdxdna_drm_create_bo *args,
- struct drm_file *filp)
+amdxdna_drm_create_dev_bo(struct drm_device *dev,
+ struct amdxdna_drm_create_bo *args, struct drm_file *filp)
{
+ size_t aligned_sz = PAGE_ALIGN(args->size);
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;
+ struct drm_gem_object *gobj;
int ret;
- abo = amdxdna_gem_create_obj(&xdna->ddev, aligned_sz);
+ if (!aligned_sz) {
+ XDNA_ERR(xdna, "Invalid BO size 0x%llx", args->size);
+ return ERR_PTR(-EINVAL);
+ }
+
+ abo = amdxdna_gem_create_obj(dev, aligned_sz);
if (IS_ERR(abo))
return abo;
-
- to_gobj(abo)->funcs = &amdxdna_gem_dev_obj_funcs;
+ gobj = to_gobj(abo);
+ gobj->funcs = &amdxdna_gem_dev_obj_funcs;
abo->type = AMDXDNA_BO_DEV;
abo->client = client;
@@ -770,31 +791,7 @@ amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
amdxdna_gem_destroy_obj(abo);
return ERR_PTR(ret);
}
-
- drm_gem_private_object_init(&xdna->ddev, to_gobj(abo), aligned_sz);
-
- return abo;
-}
-
-static struct amdxdna_gem_obj *
-amdxdna_drm_create_cmd_bo(struct drm_device *dev,
- struct amdxdna_drm_create_bo *args,
- struct drm_file *filp)
-{
- struct amdxdna_dev *xdna = to_xdna_dev(dev);
- struct amdxdna_gem_obj *abo;
-
- if (args->size < sizeof(struct amdxdna_cmd)) {
- XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
- return ERR_PTR(-EINVAL);
- }
-
- abo = amdxdna_gem_create_object(dev, args);
- if (IS_ERR(abo))
- return ERR_CAST(abo);
-
- abo->type = AMDXDNA_BO_CMD;
- abo->client = filp->driver_priv;
+ drm_gem_private_object_init(dev, gobj, aligned_sz);
return abo;
}
@@ -812,17 +809,16 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f
XDNA_DBG(xdna, "BO arg type %d vaddr 0x%llx size 0x%llx flags 0x%llx",
args->type, args->vaddr, args->size, args->flags);
switch (args->type) {
- case AMDXDNA_BO_SHMEM:
- abo = amdxdna_drm_alloc_shmem(dev, args, filp);
+ case AMDXDNA_BO_CMD:
+ fallthrough;
+ case AMDXDNA_BO_SHARE:
+ abo = amdxdna_drm_create_share_bo(dev, args, filp);
break;
case AMDXDNA_BO_DEV_HEAP:
- abo = amdxdna_drm_create_dev_heap(dev, args, filp);
+ abo = amdxdna_drm_create_dev_heap_bo(dev, args, filp);
break;
case AMDXDNA_BO_DEV:
- abo = amdxdna_drm_alloc_dev_bo(dev, args, filp);
- break;
- case AMDXDNA_BO_CMD:
- abo = amdxdna_drm_create_cmd_bo(dev, args, filp);
+ abo = amdxdna_drm_create_dev_bo(dev, args, filp);
break;
default:
return -EINVAL;
@@ -838,8 +834,8 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f
}
XDNA_DBG(xdna, "BO hdl %d type %d userptr 0x%llx xdna_addr 0x%llx size 0x%lx",
- args->handle, args->type, abo->mem.userptr,
- abo->mem.dev_addr, abo->mem.size);
+ args->handle, args->type, amdxdna_gem_uva(abo),
+ amdxdna_gem_dev_addr(abo), abo->mem.size);
put_obj:
/* Dereference object reference. Handle holds it now. */
drm_gem_object_put(to_gobj(abo));
@@ -890,38 +886,19 @@ void amdxdna_gem_unpin(struct amdxdna_gem_obj *abo)
struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
u32 bo_hdl, u8 bo_type)
{
- struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
- int ret;
gobj = drm_gem_object_lookup(client->filp, bo_hdl);
if (!gobj) {
- XDNA_DBG(xdna, "Can not find bo %d", bo_hdl);
+ XDNA_DBG(client->xdna, "Can not find bo %d", bo_hdl);
return NULL;
}
abo = to_xdna_obj(gobj);
- if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
- goto put_obj;
-
- if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
+ if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
return abo;
- if (abo->mem.size > SZ_32K) {
- XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
- goto put_obj;
- }
-
- ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
- if (ret) {
- XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
- goto put_obj;
- }
-
- return abo;
-
-put_obj:
drm_gem_object_put(gobj);
return NULL;
}
@@ -944,11 +921,8 @@ int amdxdna_drm_get_bo_info_ioctl(struct drm_device *dev, void *data, struct drm
}
abo = to_xdna_obj(gobj);
- args->vaddr = abo->mem.userptr;
- if (abo->mem.dev_addr != AMDXDNA_INVALID_ADDR)
- args->xdna_addr = abo->mem.dev_addr;
- else
- args->xdna_addr = abo->mem.dma_addr;
+ args->vaddr = amdxdna_gem_uva(abo);
+ args->xdna_addr = amdxdna_gem_dev_addr(abo);
if (abo->type != AMDXDNA_BO_DEV)
args->map_offset = drm_vma_node_offset_addr(&gobj->vma_node);
@@ -993,8 +967,8 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
if (is_import_bo(abo))
drm_clflush_sg(abo->base.sgt);
- else if (abo->mem.kva)
- drm_clflush_virt_range(abo->mem.kva + args->offset, args->size);
+ else if (amdxdna_gem_vmap(abo))
+ drm_clflush_virt_range(amdxdna_gem_vmap(abo) + args->offset, args->size);
else if (abo->base.pages)
drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT);
else
diff --git a/drivers/accel/amdxdna/amdxdna_gem.h b/drivers/accel/amdxdna/amdxdna_gem.h
index fbeb622e7cf9..a77d9344f8a4 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.h
+++ b/drivers/accel/amdxdna/amdxdna_gem.h
@@ -24,15 +24,16 @@ struct amdxdna_umap {
};
struct amdxdna_mem {
- u64 userptr;
void *kva;
- u64 dev_addr;
u64 dma_addr;
size_t size;
- struct page **pages;
- u32 nr_pages;
struct list_head umap_list;
bool map_invalid;
+ /*
+ * Cache the first mmap uva as PASID addr, which can be accessed by driver
+ * without taking notifier_lock.
+ */
+ u64 uva;
};
struct amdxdna_gem_obj {
@@ -40,11 +41,10 @@ struct amdxdna_gem_obj {
struct amdxdna_client *client;
u8 type;
bool pinned;
- struct mutex lock; /* Protects: pinned */
+ struct mutex lock; /* Protects: pinned, mem.kva */
struct amdxdna_mem mem;
- u32 ref;
- /* Below members is uninitialized when needed */
+ /* Below members are initialized when needed */
struct drm_mm mm; /* For AMDXDNA_BO_DEV_HEAP */
struct drm_mm_node mm_node; /* For AMDXDNA_BO_DEV */
u32 assigned_hwctx;
@@ -67,27 +67,29 @@ static inline void amdxdna_gem_put_obj(struct amdxdna_gem_obj *abo)
drm_gem_object_put(to_gobj(abo));
}
+void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo);
+u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo);
+u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
+
static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
{
- return abo->mem.dev_addr - abo->client->dev_heap->mem.dev_addr;
+ return amdxdna_gem_dev_addr(abo) - amdxdna_gem_dev_addr(abo->client->dev_heap);
}
-static inline u64 amdxdna_obj_dma_addr(struct amdxdna_client *client,
- struct amdxdna_gem_obj *abo)
+static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
{
- return amdxdna_pasid_on(client) ? abo->mem.userptr : abo->mem.dma_addr;
+ return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;
}
void amdxdna_umap_put(struct amdxdna_umap *mapp);
struct drm_gem_object *
-amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size);
+amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size);
struct drm_gem_object *
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);
+amdxdna_drm_create_dev_bo(struct drm_device *dev,
+ struct amdxdna_drm_create_bo *args, struct drm_file *filp);
int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo);
int amdxdna_gem_pin(struct amdxdna_gem_obj *abo);
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index 5143b8c9b92b..d83be00daf2b 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -245,7 +245,7 @@ const struct drm_driver amdxdna_drm_drv = {
.ioctls = amdxdna_drm_ioctls,
.num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),
- .gem_create_object = amdxdna_gem_create_object_cb,
+ .gem_create_object = amdxdna_gem_create_shmem_object_cb,
.gem_prime_import = amdxdna_gem_prime_import,
};
diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.c b/drivers/accel/amdxdna/amdxdna_ubuf.c
index fb71d6e3f44d..fb999aa25318 100644
--- a/drivers/accel/amdxdna/amdxdna_ubuf.c
+++ b/drivers/accel/amdxdna/amdxdna_ubuf.c
@@ -17,7 +17,6 @@
struct amdxdna_ubuf_priv {
struct page **pages;
u64 nr_pages;
- enum amdxdna_ubuf_flag flags;
struct mm_struct *mm;
};
@@ -37,11 +36,9 @@ static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
if (ret)
goto err_free_sg;
- if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) {
- ret = dma_map_sgtable(attach->dev, sg, direction, 0);
- if (ret)
- goto err_free_table;
- }
+ ret = dma_map_sgtable(attach->dev, sg, direction, 0);
+ if (ret)
+ goto err_free_table;
return sg;
@@ -56,11 +53,7 @@ static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
struct sg_table *sg,
enum dma_data_direction direction)
{
- struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
-
- if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA)
- dma_unmap_sgtable(attach->dev, sg, direction, 0);
-
+ dma_unmap_sgtable(attach->dev, sg, direction, 0);
sg_free_table(sg);
kfree(sg);
}
@@ -133,7 +126,6 @@ static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
};
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
- enum amdxdna_ubuf_flag flags,
u32 num_entries, void __user *va_entries)
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
@@ -152,7 +144,6 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
if (!ubuf)
return ERR_PTR(-ENOMEM);
- ubuf->flags = flags;
ubuf->mm = current->mm;
mmgrab(ubuf->mm);
diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.h b/drivers/accel/amdxdna/amdxdna_ubuf.h
index e5cb3bdb3ec9..8900a6dc4371 100644
--- a/drivers/accel/amdxdna/amdxdna_ubuf.h
+++ b/drivers/accel/amdxdna/amdxdna_ubuf.h
@@ -8,12 +8,7 @@
#include <drm/drm_device.h>
#include <linux/dma-buf.h>
-enum amdxdna_ubuf_flag {
- AMDXDNA_UBUF_FLAG_MAP_DMA = 1,
-};
-
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
- enum amdxdna_ubuf_flag flags,
u32 num_entries, void __user *va_entries);
#endif /* _AMDXDNA_UBUF_H_ */
diff --git a/include/uapi/drm/amdxdna_accel.h b/include/uapi/drm/amdxdna_accel.h
index 5bd13f4435f5..bddaaaf945cf 100644
--- a/include/uapi/drm/amdxdna_accel.h
+++ b/include/uapi/drm/amdxdna_accel.h
@@ -156,10 +156,11 @@ struct amdxdna_drm_config_hwctx {
enum amdxdna_bo_type {
AMDXDNA_BO_INVALID = 0,
- AMDXDNA_BO_SHMEM,
- AMDXDNA_BO_DEV_HEAP,
- AMDXDNA_BO_DEV,
- AMDXDNA_BO_CMD,
+ AMDXDNA_BO_SHMEM = 1, /* Be compatible with legacy application code. */
+ AMDXDNA_BO_SHARE = 1,
+ AMDXDNA_BO_DEV_HEAP = 2,
+ AMDXDNA_BO_DEV = 3,
+ AMDXDNA_BO_CMD = 4,
};
/**
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval
2026-03-20 21:06 [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval Lizhi Hou
@ 2026-03-20 21:46 ` Mario Limonciello (AMD) (kernel.org)
2026-03-21 5:26 ` Lizhi Hou
2026-03-21 17:20 ` Claude review: " Claude Code Review Bot
2026-03-21 17:20 ` Claude Code Review Bot
2 siblings, 1 reply; 5+ messages in thread
From: Mario Limonciello (AMD) (kernel.org) @ 2026-03-20 21:46 UTC (permalink / raw)
To: Lizhi Hou, ogabbay, quic_jhugo, dri-devel, maciej.falkowski
Cc: Max Zhen, linux-kernel, sonal.santan
On 3/20/2026 4:06 PM, Lizhi Hou wrote:
> From: Max Zhen <max.zhen@amd.com>
>
> Refactor amdxdna GEM buffer object (BO) handling to simplify address
> management and unify BO type semantics.
>
> Introduce helper APIs to retrieve commonly used BO addresses:
> - User virtual address (UVA)
> - Kernel virtual address (KVA)
> - Device address (IOVA/PA)
>
> These helpers centralize address lookup logic and avoid duplicating
> BO-specific handling across submission and execution paths. This also
> improves readability and reduces the risk of inconsistent address
> handling in future changes.
>
> As part of the refactor:
> - Rename SHMEM BO type to SHARE to better reflect its usage.
> - Merge CMD BO handling into SHARE, removing special-case logic for
> command buffers.
> - Consolidate BO type handling paths to reduce code duplication and
> simplify maintenance.
>
> No functional change is intended. The refactor prepares the driver for
> future enhancements by providing a cleaner abstraction for BO address
> management.
>
> Signed-off-by: Max Zhen <max.zhen@amd.com>
You forgot to include your S-o-b in the bump. Please include it when
committing.
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
> drivers/accel/amdxdna/aie2_ctx.c | 8 +-
> drivers/accel/amdxdna/aie2_message.c | 33 +-
> drivers/accel/amdxdna/amdxdna_ctx.c | 23 +-
> drivers/accel/amdxdna/amdxdna_ctx.h | 15 +-
> drivers/accel/amdxdna/amdxdna_gem.c | 400 +++++++++++-------------
> drivers/accel/amdxdna/amdxdna_gem.h | 32 +-
> drivers/accel/amdxdna/amdxdna_pci_drv.c | 2 +-
> drivers/accel/amdxdna/amdxdna_ubuf.c | 17 +-
> drivers/accel/amdxdna/amdxdna_ubuf.h | 5 -
> include/uapi/drm/amdxdna_accel.h | 9 +-
> 10 files changed, 266 insertions(+), 278 deletions(-)
>
> diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
> index 6292349868c5..66dbbfd322a2 100644
> --- a/drivers/accel/amdxdna/aie2_ctx.c
> +++ b/drivers/accel/amdxdna/aie2_ctx.c
> @@ -79,7 +79,7 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
> }
>
> ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
> - amdxdna_obj_dma_addr(hwctx->client, heap),
> + amdxdna_obj_dma_addr(heap),
> heap->mem.size);
> if (ret) {
> XDNA_ERR(xdna, "Map host buf failed, ret %d", ret);
> @@ -659,14 +659,14 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
> .size = MAX_CHAIN_CMDBUF_SIZE,
> };
>
> - abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp);
> + abo = amdxdna_drm_create_dev_bo(&xdna->ddev, &args, client->filp);
> if (IS_ERR(abo)) {
> ret = PTR_ERR(abo);
> goto free_cmd_bufs;
> }
>
> XDNA_DBG(xdna, "Command buf %d addr 0x%llx size 0x%lx",
> - i, abo->mem.dev_addr, abo->mem.size);
> + i, amdxdna_gem_dev_addr(abo), abo->mem.size);
> priv->cmd_buf[i] = abo;
> }
>
> @@ -707,7 +707,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
> }
>
> ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
> - amdxdna_obj_dma_addr(hwctx->client, heap),
> + amdxdna_obj_dma_addr(heap),
> heap->mem.size);
> if (ret) {
> XDNA_ERR(xdna, "Map host buffer failed, ret %d", ret);
> diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c
> index 4ec591306854..6e3fb52aa35f 100644
> --- a/drivers/accel/amdxdna/aie2_message.c
> +++ b/drivers/accel/amdxdna/aie2_message.c
> @@ -548,10 +548,10 @@ int aie2_config_cu(struct amdxdna_hwctx *hwctx,
> }
>
> req.cfgs[i] = FIELD_PREP(AIE2_MSG_CFG_CU_PDI_ADDR,
> - abo->mem.dev_addr >> shift);
> + amdxdna_gem_dev_addr(abo) >> shift);
> req.cfgs[i] |= FIELD_PREP(AIE2_MSG_CFG_CU_FUNC, cu->cu_func);
> XDNA_DBG(xdna, "CU %d full addr 0x%llx, cfg 0x%x", i,
> - abo->mem.dev_addr, req.cfgs[i]);
> + amdxdna_gem_dev_addr(abo), req.cfgs[i]);
> drm_gem_object_put(gobj);
> }
> req.num_cus = hwctx->cus->num_cus;
> @@ -998,6 +998,7 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
> struct mailbox_channel *chann = hwctx->priv->mbox_chann;
> struct amdxdna_client *client = hwctx->client;
> struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
> + void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
> struct amdxdna_dev *xdna = client->xdna;
> struct amdxdna_cmd_chain *payload;
> struct xdna_mailbox_msg msg;
> @@ -1009,6 +1010,9 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
> u32 op;
> u32 i;
>
> + if (!cmd_buf)
> + return -ENOMEM;
> +
> op = amdxdna_cmd_get_op(cmd_abo);
> payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len);
> if (op != ERT_CMD_CHAIN) {
> @@ -1032,15 +1036,14 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
> u32 boh = (u32)(payload->data[i]);
> struct amdxdna_gem_obj *abo;
>
> - abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_CMD);
> + abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_SHMEM);
> if (!abo) {
> XDNA_ERR(xdna, "Failed to find cmd BO %d", boh);
> return -ENOENT;
> }
>
> size = cmdbuf_abo->mem.size - offset;
> - ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva + offset,
> - abo, &size, &op);
> + ret = aie2_cmdlist_fill_slot(cmd_buf + offset, abo, &size, &op);
> amdxdna_gem_put_obj(abo);
> if (ret)
> return ret;
> @@ -1050,16 +1053,16 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
>
> XDNA_DBG(xdna, "Total %d commands:", ccnt);
> print_hex_dump_debug("cmdbufs: ", DUMP_PREFIX_OFFSET, 16, 4,
> - cmdbuf_abo->mem.kva, offset, false);
> + cmd_buf, offset, false);
>
> msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
> if (msg.opcode == MSG_OP_MAX_OPCODE)
> return -EOPNOTSUPP;
>
> /* The offset is the accumulated total size of the cmd buffer */
> - EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr,
> + EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo),
> offset, ccnt);
> - drm_clflush_virt_range(cmdbuf_abo->mem.kva, offset);
> + drm_clflush_virt_range(cmd_buf, offset);
>
> msg.handle = job;
> msg.notify_cb = notify_cb;
> @@ -1084,27 +1087,29 @@ int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx,
> struct mailbox_channel *chann = hwctx->priv->mbox_chann;
> struct amdxdna_dev *xdna = hwctx->client->xdna;
> struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
> + void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
> struct xdna_mailbox_msg msg;
> union exec_chain_req req;
> u32 op = ERT_INVALID_CMD;
> size_t size;
> int ret;
>
> + if (!cmd_buf)
> + return -ENOMEM;
> +
> size = cmdbuf_abo->mem.size;
> - ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva, cmd_abo, &size, &op);
> + ret = aie2_cmdlist_fill_slot(cmd_buf, cmd_abo, &size, &op);
> if (ret)
> return ret;
>
> - print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4,
> - cmdbuf_abo->mem.kva, size, false);
> + print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4, cmd_buf, size, false);
>
> msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
> if (msg.opcode == MSG_OP_MAX_OPCODE)
> return -EOPNOTSUPP;
>
> - EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr,
> - size, 1);
> - drm_clflush_virt_range(cmdbuf_abo->mem.kva, size);
> + EXEC_MSG_OPS(xdna)->init_chain_req(&req, amdxdna_gem_dev_addr(cmdbuf_abo), size, 1);
> + drm_clflush_virt_range(cmd_buf, size);
>
> msg.handle = job;
> msg.notify_cb = notify_cb;
> diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c
> index 4b921715176d..94e5639adc64 100644
> --- a/drivers/accel/amdxdna/amdxdna_ctx.c
> +++ b/drivers/accel/amdxdna/amdxdna_ctx.c
> @@ -94,9 +94,12 @@ int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg,
>
> void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
> {
> - struct amdxdna_cmd *cmd = abo->mem.kva;
> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
> u32 num_masks, count;
>
> + if (!cmd)
> + return NULL;
> +
> if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
> num_masks = 0;
> else
> @@ -118,10 +121,13 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
>
> u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo)
> {
> - struct amdxdna_cmd *cmd = abo->mem.kva;
> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
> u32 num_masks, i;
> u32 *cu_mask;
>
> + if (!cmd)
> + return INVALID_CU_IDX;
> +
> if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
> return INVALID_CU_IDX;
>
> @@ -141,19 +147,24 @@ int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
> void *err_data, size_t size)
> {
> struct amdxdna_client *client = job->hwctx->client;
> - struct amdxdna_cmd *cmd = abo->mem.kva;
> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
> struct amdxdna_cmd_chain *cc = NULL;
>
> + if (!cmd)
> + return -ENOMEM;
> +
> cmd->header &= ~AMDXDNA_CMD_STATE;
> cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
>
> if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) {
> cc = amdxdna_cmd_get_payload(abo, NULL);
> cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0;
> - abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD);
> + abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_SHMEM);
> if (!abo)
> return -EINVAL;
> - cmd = abo->mem.kva;
> + cmd = amdxdna_gem_vmap(abo);
> + if (!cmd)
> + return -ENOMEM;
> }
>
> memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd));
> @@ -472,7 +483,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client,
> job->drv_cmd = drv_cmd;
>
> if (cmd_bo_hdl != AMDXDNA_INVALID_BO_HANDLE) {
> - job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl, AMDXDNA_BO_CMD);
> + job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl, AMDXDNA_BO_SHMEM);
> if (!job->cmd_bo) {
> XDNA_ERR(xdna, "Failed to get cmd bo from %d", cmd_bo_hdl);
> ret = -EINVAL;
> diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h
> index 57db1527a93b..a8557d7e8923 100644
> --- a/drivers/accel/amdxdna/amdxdna_ctx.h
> +++ b/drivers/accel/amdxdna/amdxdna_ctx.h
> @@ -158,7 +158,10 @@ struct amdxdna_sched_job {
> static inline u32
> amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
> {
> - struct amdxdna_cmd *cmd = abo->mem.kva;
> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
> +
> + if (!cmd)
> + return ERT_INVALID_CMD;
>
> return FIELD_GET(AMDXDNA_CMD_OPCODE, cmd->header);
> }
> @@ -166,7 +169,10 @@ amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
> static inline void
> amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum ert_cmd_state s)
> {
> - struct amdxdna_cmd *cmd = abo->mem.kva;
> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
> +
> + if (!cmd)
> + return;
>
> cmd->header &= ~AMDXDNA_CMD_STATE;
> cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, s);
> @@ -175,7 +181,10 @@ amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum ert_cmd_state s)
> static inline enum ert_cmd_state
> amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo)
> {
> - struct amdxdna_cmd *cmd = abo->mem.kva;
> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
> +
> + if (!cmd)
> + return ERT_CMD_STATE_INVALID;
>
> return FIELD_GET(AMDXDNA_CMD_STATE, cmd->header);
> }
> diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
> index d80cf164740c..3c15d06b6048 100644
> --- a/drivers/accel/amdxdna/amdxdna_gem.c
> +++ b/drivers/accel/amdxdna/amdxdna_gem.c
> @@ -30,7 +30,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
> struct amdxdna_dev *xdna = client->xdna;
> struct amdxdna_mem *mem = &abo->mem;
> struct amdxdna_gem_obj *heap;
> - u64 offset;
> u32 align;
> int ret;
>
> @@ -42,7 +41,7 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
> goto unlock_out;
> }
>
> - if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) {
> + if (amdxdna_gem_uva(heap) == AMDXDNA_INVALID_ADDR) {
> XDNA_ERR(xdna, "Invalid dev heap userptr");
> ret = -EINVAL;
> goto unlock_out;
> @@ -64,11 +63,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
> goto unlock_out;
> }
>
> - mem->dev_addr = abo->mm_node.start;
> - 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:
> @@ -77,13 +71,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
> 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)
> {
> @@ -99,6 +86,105 @@ amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo)
> mutex_unlock(&abo->client->mm_lock);
> }
>
> +static struct amdxdna_gem_obj *
> +amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
> +{
> + struct amdxdna_gem_obj *abo;
> +
> + abo = kzalloc_obj(*abo);
> + if (!abo)
> + return ERR_PTR(-ENOMEM);
> +
> + abo->pinned = false;
> + abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
> + mutex_init(&abo->lock);
> +
> + abo->mem.dma_addr = AMDXDNA_INVALID_ADDR;
> + abo->mem.uva = AMDXDNA_INVALID_ADDR;
> + abo->mem.size = size;
> + INIT_LIST_HEAD(&abo->mem.umap_list);
> +
> + return abo;
> +}
> +
> +static void
> +amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
> +{
> + mutex_destroy(&abo->lock);
> + kfree(abo);
> +}
> +
> +/*
> + * Obtains a kernel virtual address on the BO (usually of small size).
> + * The mapping is established on the first call and stays valid until
> + * amdxdna_gem_vunmap() is called.
> + */
> +void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
> +{
> + struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
> + int ret;
> +
> + if (abo->mem.kva)
> + return abo->mem.kva;
> +
> + /* The first call to get the kva, taking slow path. */
> + guard(mutex)(&abo->lock);
> +
> + if (!abo->mem.kva) {
> + ret = drm_gem_vmap(to_gobj(abo), &map);
> + if (ret)
> + XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
> + else
> + abo->mem.kva = map.vaddr;
> + }
> + return abo->mem.kva;
> +}
> +
> +/*
> + * Free mapping established through amdxdna_gem_vmap()
> + */
> +static void amdxdna_gem_vunmap(struct amdxdna_gem_obj *abo)
> +{
> + guard(mutex)(&abo->lock);
> +
> + if (abo->mem.kva) {
> + struct iosys_map map = IOSYS_MAP_INIT_VADDR(abo->mem.kva);
> +
> + drm_gem_vunmap(to_gobj(abo), &map);
> + abo->mem.kva = NULL;
> + }
> +}
> +
> +/*
> + * Obtain the user virtual address for accessing the BO.
> + * It can be used for device to access the BO when PASID is enabled.
> + */
> +u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo)
> +{
> + if (abo->type == AMDXDNA_BO_DEV) {
> + struct amdxdna_gem_obj *heap = abo->client->dev_heap;
> + u64 off = amdxdna_dev_bo_offset(abo);
> +
> + if (amdxdna_gem_uva(heap) != AMDXDNA_INVALID_ADDR)
> + return amdxdna_gem_uva(heap) + off;
> + return AMDXDNA_INVALID_ADDR;
> + }
> +
> + return abo->mem.uva;
> +}
> +
> +/*
> + * Obtain the address for device to access the BO.
> + */
> +u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo)
> +{
> + if (abo->type == AMDXDNA_BO_DEV_HEAP)
> + return abo->client->xdna->dev_info->dev_mem_base;
> + if (abo->type == AMDXDNA_BO_DEV)
> + return abo->mm_node.start;
> + return amdxdna_obj_dma_addr(abo);
> +}
> +
> static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
> const struct mmu_notifier_range *range,
> unsigned long cur_seq)
> @@ -161,16 +247,19 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
> static void amdxdna_umap_release(struct kref *ref)
> {
> struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
> + struct amdxdna_gem_obj *abo = mapp->abo;
> struct vm_area_struct *vma = mapp->vma;
> struct amdxdna_dev *xdna;
>
> mmu_interval_notifier_remove(&mapp->notifier);
> - if (is_import_bo(mapp->abo) && vma->vm_file && vma->vm_file->f_mapping)
> + if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
> mapping_clear_unevictable(vma->vm_file->f_mapping);
>
> xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
> down_write(&xdna->notifier_lock);
> list_del(&mapp->node);
> + if (list_empty(&abo->mem.umap_list))
> + abo->mem.uva = AMDXDNA_INVALID_ADDR;
> up_write(&xdna->notifier_lock);
>
> kvfree(mapp->range.hmm_pfns);
> @@ -232,13 +321,13 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
> mapp->abo = abo;
> kref_init(&mapp->refcnt);
>
> - if (abo->mem.userptr == AMDXDNA_INVALID_ADDR)
> - abo->mem.userptr = addr;
> INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
> if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
> mapping_set_unevictable(vma->vm_file->f_mapping);
>
> down_write(&xdna->notifier_lock);
> + if (list_empty(&abo->mem.umap_list))
> + abo->mem.uva = addr;
> list_add_tail(&mapp->node, &abo->mem.umap_list);
> up_write(&xdna->notifier_lock);
>
> @@ -256,10 +345,11 @@ 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);
> + XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, amdxdna_gem_dev_addr(abo));
> if (abo->pinned)
> amdxdna_gem_unpin(abo);
>
> + amdxdna_gem_vunmap(abo);
> amdxdna_gem_heap_free(abo);
> drm_gem_object_release(gobj);
> amdxdna_gem_destroy_obj(abo);
> @@ -390,35 +480,6 @@ static const struct dma_buf_ops amdxdna_dmabuf_ops = {
> .vunmap = drm_gem_dmabuf_vunmap,
> };
>
> -static int amdxdna_gem_obj_vmap(struct amdxdna_gem_obj *abo, void **vaddr)
> -{
> - struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
> - int ret;
> -
> - if (is_import_bo(abo))
> - ret = dma_buf_vmap_unlocked(abo->dma_buf, &map);
> - else
> - ret = drm_gem_vmap(to_gobj(abo), &map);
> -
> - *vaddr = map.vaddr;
> - return ret;
> -}
> -
> -static void amdxdna_gem_obj_vunmap(struct amdxdna_gem_obj *abo)
> -{
> - struct iosys_map map;
> -
> - if (!abo->mem.kva)
> - return;
> -
> - iosys_map_set_vaddr(&map, abo->mem.kva);
> -
> - if (is_import_bo(abo))
> - dma_buf_vunmap_unlocked(abo->dma_buf, &map);
> - else
> - drm_gem_vunmap(to_gobj(abo), &map);
> -}
> -
> static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags)
> {
> struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
> @@ -452,7 +513,7 @@ static void amdxdna_gem_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);
> + XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, amdxdna_gem_dev_addr(abo));
>
> amdxdna_hmm_unregister(abo, NULL);
> flush_workqueue(xdna->notifier_wq);
> @@ -463,15 +524,16 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj)
> if (abo->type == AMDXDNA_BO_DEV_HEAP)
> drm_mm_takedown(&abo->mm);
>
> - amdxdna_gem_obj_vunmap(abo);
> + if (amdxdna_iova_on(xdna))
> + amdxdna_iommu_unmap_bo(xdna, abo);
> +
> + amdxdna_gem_vunmap(abo);
> mutex_destroy(&abo->lock);
>
> - if (is_import_bo(abo)) {
> + if (is_import_bo(abo))
> amdxdna_imported_obj_free(abo);
> - return;
> - }
> -
> - drm_gem_shmem_free(&abo->base);
> + else
> + drm_gem_shmem_free(&abo->base);
> }
>
> static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *filp)
> @@ -481,43 +543,38 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi
> int ret;
>
> guard(mutex)(&abo->lock);
> - if (abo->ref) {
> - abo->ref++;
> - return 0;
> - }
>
> + if (!abo->client)
> + abo->client = filp->driver_priv;
> if (amdxdna_iova_on(xdna)) {
> ret = amdxdna_iommu_map_bo(xdna, abo);
> if (ret)
> return ret;
> }
> - abo->ref++;
>
> return 0;
> }
>
> -static void amdxdna_gem_obj_close(struct drm_gem_object *gobj, struct drm_file *filp)
> +static int amdxdna_gem_dev_obj_vmap(struct drm_gem_object *obj, struct iosys_map *map)
> {
> - struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev);
> - struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
> + struct amdxdna_gem_obj *abo = to_xdna_obj(obj);
> + void *base = amdxdna_gem_vmap(abo->client->dev_heap);
> + u64 offset = amdxdna_dev_bo_offset(abo);
>
> - guard(mutex)(&abo->lock);
> - abo->ref--;
> - if (abo->ref)
> - return;
> -
> - if (amdxdna_iova_on(xdna))
> - amdxdna_iommu_unmap_bo(xdna, abo);
> + if (!base)
> + return -ENOMEM;
> + iosys_map_set_vaddr(map, base + offset);
> + return 0;
> }
>
> static const struct drm_gem_object_funcs amdxdna_gem_dev_obj_funcs = {
> .free = amdxdna_gem_dev_obj_free,
> + .vmap = amdxdna_gem_dev_obj_vmap,
> };
>
> static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
> .free = amdxdna_gem_obj_free,
> .open = amdxdna_gem_obj_open,
> - .close = amdxdna_gem_obj_close,
> .print_info = drm_gem_shmem_object_print_info,
> .pin = drm_gem_shmem_object_pin,
> .unpin = drm_gem_shmem_object_unpin,
> @@ -529,31 +586,9 @@ static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
> .export = amdxdna_gem_prime_export,
> };
>
> -static struct amdxdna_gem_obj *
> -amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
> -{
> - struct amdxdna_gem_obj *abo;
> -
> - abo = kzalloc_obj(*abo);
> - if (!abo)
> - return ERR_PTR(-ENOMEM);
> -
> - abo->pinned = false;
> - abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
> - mutex_init(&abo->lock);
> -
> - abo->mem.userptr = AMDXDNA_INVALID_ADDR;
> - abo->mem.dev_addr = AMDXDNA_INVALID_ADDR;
> - abo->mem.dma_addr = AMDXDNA_INVALID_ADDR;
> - abo->mem.size = size;
> - INIT_LIST_HEAD(&abo->mem.umap_list);
> -
> - return abo;
> -}
> -
> /* For drm_driver->gem_create_object callback */
> struct drm_gem_object *
> -amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
> +amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size)
> {
> struct amdxdna_gem_obj *abo;
>
> @@ -567,8 +602,9 @@ amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
> }
>
> static struct amdxdna_gem_obj *
> -amdxdna_gem_create_shmem_object(struct drm_device *dev, size_t size)
> +amdxdna_gem_create_shmem_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args)
> {
> + size_t size = args->size;
> struct drm_gem_shmem_object *shmem = drm_gem_shmem_create(dev, size);
>
> if (IS_ERR(shmem))
> @@ -582,7 +618,6 @@ static struct amdxdna_gem_obj *
> amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args)
> {
> struct amdxdna_dev *xdna = to_xdna_dev(dev);
> - enum amdxdna_ubuf_flag flags = 0;
> struct amdxdna_drm_va_tbl va_tbl;
> struct drm_gem_object *gobj;
> struct dma_buf *dma_buf;
> @@ -593,10 +628,7 @@ amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create
> }
>
> if (va_tbl.num_entries) {
> - if (args->type == AMDXDNA_BO_CMD)
> - flags |= AMDXDNA_UBUF_FLAG_MAP_DMA;
> -
> - dma_buf = amdxdna_get_ubuf(dev, flags, va_tbl.num_entries,
> + dma_buf = amdxdna_get_ubuf(dev, va_tbl.num_entries,
> u64_to_user_ptr(args->vaddr + sizeof(va_tbl)));
> } else {
> dma_buf = dma_buf_get(va_tbl.dmabuf_fd);
> @@ -616,18 +648,6 @@ amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create
> return to_xdna_obj(gobj);
> }
>
> -static struct amdxdna_gem_obj *
> -amdxdna_gem_create_object(struct drm_device *dev,
> - struct amdxdna_drm_create_bo *args)
> -{
> - size_t aligned_sz = PAGE_ALIGN(args->size);
> -
> - if (args->vaddr)
> - return amdxdna_gem_create_ubuf_object(dev, args);
> -
> - return amdxdna_gem_create_shmem_object(dev, aligned_sz);
> -}
> -
> struct drm_gem_object *
> amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
> {
> @@ -660,7 +680,8 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
> abo = to_xdna_obj(gobj);
> abo->attach = attach;
> abo->dma_buf = dma_buf;
> - abo->type = AMDXDNA_BO_SHMEM;
> + abo->type = AMDXDNA_BO_SHARE;
> + gobj->resv = dma_buf->resv;
>
> return gobj;
>
> @@ -675,92 +696,92 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
> }
>
> static struct amdxdna_gem_obj *
> -amdxdna_drm_alloc_shmem(struct drm_device *dev,
> - struct amdxdna_drm_create_bo *args,
> - struct drm_file *filp)
> +amdxdna_drm_create_share_bo(struct drm_device *dev,
> + struct amdxdna_drm_create_bo *args, struct drm_file *filp)
> {
> - struct amdxdna_client *client = filp->driver_priv;
> struct amdxdna_gem_obj *abo;
>
> - abo = amdxdna_gem_create_object(dev, args);
> + if (args->vaddr)
> + abo = amdxdna_gem_create_ubuf_object(dev, args);
> + else
> + abo = amdxdna_gem_create_shmem_object(dev, args);
> if (IS_ERR(abo))
> return ERR_CAST(abo);
>
> - abo->client = client;
> - abo->type = AMDXDNA_BO_SHMEM;
> + if (args->type == AMDXDNA_BO_DEV_HEAP)
> + abo->type = AMDXDNA_BO_DEV_HEAP;
> + else
> + abo->type = AMDXDNA_BO_SHARE;
>
> return abo;
> }
>
> static struct amdxdna_gem_obj *
> -amdxdna_drm_create_dev_heap(struct drm_device *dev,
> - struct amdxdna_drm_create_bo *args,
> - struct drm_file *filp)
> +amdxdna_drm_create_dev_heap_bo(struct drm_device *dev,
> + struct amdxdna_drm_create_bo *args, struct drm_file *filp)
> {
> struct amdxdna_client *client = filp->driver_priv;
> struct amdxdna_dev *xdna = to_xdna_dev(dev);
> struct amdxdna_gem_obj *abo;
> int ret;
>
> - if (args->size > xdna->dev_info->dev_mem_size) {
> - XDNA_DBG(xdna, "Invalid dev heap size 0x%llx, limit 0x%lx",
> + WARN_ON(!is_power_of_2(xdna->dev_info->dev_mem_size));
> + XDNA_DBG(xdna, "Requested dev heap size 0x%llx", args->size);
> + if (!args->size || !IS_ALIGNED(args->size, xdna->dev_info->dev_mem_size)) {
> + XDNA_ERR(xdna, "The dev heap size 0x%llx is not multiple of 0x%lx",
> args->size, xdna->dev_info->dev_mem_size);
> return ERR_PTR(-EINVAL);
> }
>
> + /* HEAP BO is a special case of SHMEM BO. */
> + abo = amdxdna_drm_create_share_bo(dev, args, filp);
> + if (IS_ERR(abo))
> + return ERR_CAST(abo);
> +
> + /* Set up heap for this client. */
> mutex_lock(&client->mm_lock);
> +
> if (client->dev_heap) {
> XDNA_DBG(client->xdna, "dev heap is already created");
> ret = -EBUSY;
> goto mm_unlock;
> }
> -
> - abo = amdxdna_gem_create_object(dev, args);
> - if (IS_ERR(abo)) {
> - ret = PTR_ERR(abo);
> - goto mm_unlock;
> - }
> -
> - 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 = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
> - if (ret) {
> - XDNA_ERR(xdna, "Vmap heap bo failed, ret %d", ret);
> - goto release_obj;
> - }
> -
> client->dev_heap = abo;
> drm_gem_object_get(to_gobj(abo));
> +
> + drm_mm_init(&abo->mm, xdna->dev_info->dev_mem_base, abo->mem.size);
> +
> mutex_unlock(&client->mm_lock);
>
> return abo;
>
> -release_obj:
> - drm_gem_object_put(to_gobj(abo));
> mm_unlock:
> mutex_unlock(&client->mm_lock);
> + drm_gem_object_put(to_gobj(abo));
> return ERR_PTR(ret);
> }
>
> struct amdxdna_gem_obj *
> -amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
> - struct amdxdna_drm_create_bo *args,
> - struct drm_file *filp)
> +amdxdna_drm_create_dev_bo(struct drm_device *dev,
> + struct amdxdna_drm_create_bo *args, struct drm_file *filp)
> {
> + size_t aligned_sz = PAGE_ALIGN(args->size);
> 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;
> + struct drm_gem_object *gobj;
> int ret;
>
> - abo = amdxdna_gem_create_obj(&xdna->ddev, aligned_sz);
> + if (!aligned_sz) {
> + XDNA_ERR(xdna, "Invalid BO size 0x%llx", args->size);
> + return ERR_PTR(-EINVAL);
> + }
> +
> + abo = amdxdna_gem_create_obj(dev, aligned_sz);
> if (IS_ERR(abo))
> return abo;
> -
> - to_gobj(abo)->funcs = &amdxdna_gem_dev_obj_funcs;
> + gobj = to_gobj(abo);
> + gobj->funcs = &amdxdna_gem_dev_obj_funcs;
> abo->type = AMDXDNA_BO_DEV;
> abo->client = client;
>
> @@ -770,31 +791,7 @@ amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
> amdxdna_gem_destroy_obj(abo);
> return ERR_PTR(ret);
> }
> -
> - drm_gem_private_object_init(&xdna->ddev, to_gobj(abo), aligned_sz);
> -
> - return abo;
> -}
> -
> -static struct amdxdna_gem_obj *
> -amdxdna_drm_create_cmd_bo(struct drm_device *dev,
> - struct amdxdna_drm_create_bo *args,
> - struct drm_file *filp)
> -{
> - struct amdxdna_dev *xdna = to_xdna_dev(dev);
> - struct amdxdna_gem_obj *abo;
> -
> - if (args->size < sizeof(struct amdxdna_cmd)) {
> - XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
> - return ERR_PTR(-EINVAL);
> - }
> -
> - abo = amdxdna_gem_create_object(dev, args);
> - if (IS_ERR(abo))
> - return ERR_CAST(abo);
> -
> - abo->type = AMDXDNA_BO_CMD;
> - abo->client = filp->driver_priv;
> + drm_gem_private_object_init(dev, gobj, aligned_sz);
>
> return abo;
> }
> @@ -812,17 +809,16 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f
> XDNA_DBG(xdna, "BO arg type %d vaddr 0x%llx size 0x%llx flags 0x%llx",
> args->type, args->vaddr, args->size, args->flags);
> switch (args->type) {
> - case AMDXDNA_BO_SHMEM:
> - abo = amdxdna_drm_alloc_shmem(dev, args, filp);
> + case AMDXDNA_BO_CMD:
> + fallthrough;
> + case AMDXDNA_BO_SHARE:
> + abo = amdxdna_drm_create_share_bo(dev, args, filp);
> break;
> case AMDXDNA_BO_DEV_HEAP:
> - abo = amdxdna_drm_create_dev_heap(dev, args, filp);
> + abo = amdxdna_drm_create_dev_heap_bo(dev, args, filp);
> break;
> case AMDXDNA_BO_DEV:
> - abo = amdxdna_drm_alloc_dev_bo(dev, args, filp);
> - break;
> - case AMDXDNA_BO_CMD:
> - abo = amdxdna_drm_create_cmd_bo(dev, args, filp);
> + abo = amdxdna_drm_create_dev_bo(dev, args, filp);
> break;
> default:
> return -EINVAL;
> @@ -838,8 +834,8 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f
> }
>
> XDNA_DBG(xdna, "BO hdl %d type %d userptr 0x%llx xdna_addr 0x%llx size 0x%lx",
> - args->handle, args->type, abo->mem.userptr,
> - abo->mem.dev_addr, abo->mem.size);
> + args->handle, args->type, amdxdna_gem_uva(abo),
> + amdxdna_gem_dev_addr(abo), abo->mem.size);
> put_obj:
> /* Dereference object reference. Handle holds it now. */
> drm_gem_object_put(to_gobj(abo));
> @@ -890,38 +886,19 @@ void amdxdna_gem_unpin(struct amdxdna_gem_obj *abo)
> struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
> u32 bo_hdl, u8 bo_type)
> {
> - struct amdxdna_dev *xdna = client->xdna;
> struct amdxdna_gem_obj *abo;
> struct drm_gem_object *gobj;
> - int ret;
>
> gobj = drm_gem_object_lookup(client->filp, bo_hdl);
> if (!gobj) {
> - XDNA_DBG(xdna, "Can not find bo %d", bo_hdl);
> + XDNA_DBG(client->xdna, "Can not find bo %d", bo_hdl);
> return NULL;
> }
>
> abo = to_xdna_obj(gobj);
> - if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
> - goto put_obj;
> -
> - if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
> + if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
> return abo;
>
> - if (abo->mem.size > SZ_32K) {
> - XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
> - goto put_obj;
> - }
> -
> - ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
> - if (ret) {
> - XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
> - goto put_obj;
> - }
> -
> - return abo;
> -
> -put_obj:
> drm_gem_object_put(gobj);
> return NULL;
> }
> @@ -944,11 +921,8 @@ int amdxdna_drm_get_bo_info_ioctl(struct drm_device *dev, void *data, struct drm
> }
>
> abo = to_xdna_obj(gobj);
> - args->vaddr = abo->mem.userptr;
> - if (abo->mem.dev_addr != AMDXDNA_INVALID_ADDR)
> - args->xdna_addr = abo->mem.dev_addr;
> - else
> - args->xdna_addr = abo->mem.dma_addr;
> + args->vaddr = amdxdna_gem_uva(abo);
> + args->xdna_addr = amdxdna_gem_dev_addr(abo);
>
> if (abo->type != AMDXDNA_BO_DEV)
> args->map_offset = drm_vma_node_offset_addr(&gobj->vma_node);
> @@ -993,8 +967,8 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
>
> if (is_import_bo(abo))
> drm_clflush_sg(abo->base.sgt);
> - else if (abo->mem.kva)
> - drm_clflush_virt_range(abo->mem.kva + args->offset, args->size);
> + else if (amdxdna_gem_vmap(abo))
> + drm_clflush_virt_range(amdxdna_gem_vmap(abo) + args->offset, args->size);
> else if (abo->base.pages)
> drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT);
> else
> diff --git a/drivers/accel/amdxdna/amdxdna_gem.h b/drivers/accel/amdxdna/amdxdna_gem.h
> index fbeb622e7cf9..a77d9344f8a4 100644
> --- a/drivers/accel/amdxdna/amdxdna_gem.h
> +++ b/drivers/accel/amdxdna/amdxdna_gem.h
> @@ -24,15 +24,16 @@ struct amdxdna_umap {
> };
>
> struct amdxdna_mem {
> - u64 userptr;
> void *kva;
> - u64 dev_addr;
> u64 dma_addr;
> size_t size;
> - struct page **pages;
> - u32 nr_pages;
> struct list_head umap_list;
> bool map_invalid;
> + /*
> + * Cache the first mmap uva as PASID addr, which can be accessed by driver
> + * without taking notifier_lock.
> + */
> + u64 uva;
> };
>
> struct amdxdna_gem_obj {
> @@ -40,11 +41,10 @@ struct amdxdna_gem_obj {
> struct amdxdna_client *client;
> u8 type;
> bool pinned;
> - struct mutex lock; /* Protects: pinned */
> + struct mutex lock; /* Protects: pinned, mem.kva */
> struct amdxdna_mem mem;
> - u32 ref;
>
> - /* Below members is uninitialized when needed */
> + /* Below members are initialized when needed */
> struct drm_mm mm; /* For AMDXDNA_BO_DEV_HEAP */
> struct drm_mm_node mm_node; /* For AMDXDNA_BO_DEV */
> u32 assigned_hwctx;
> @@ -67,27 +67,29 @@ static inline void amdxdna_gem_put_obj(struct amdxdna_gem_obj *abo)
> drm_gem_object_put(to_gobj(abo));
> }
>
> +void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo);
> +u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo);
> +u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
> +
> static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
> {
> - return abo->mem.dev_addr - abo->client->dev_heap->mem.dev_addr;
> + return amdxdna_gem_dev_addr(abo) - amdxdna_gem_dev_addr(abo->client->dev_heap);
> }
>
> -static inline u64 amdxdna_obj_dma_addr(struct amdxdna_client *client,
> - struct amdxdna_gem_obj *abo)
> +static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
> {
> - return amdxdna_pasid_on(client) ? abo->mem.userptr : abo->mem.dma_addr;
> + return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;
> }
>
> void amdxdna_umap_put(struct amdxdna_umap *mapp);
>
> struct drm_gem_object *
> -amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size);
> +amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size);
> struct drm_gem_object *
> 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);
> +amdxdna_drm_create_dev_bo(struct drm_device *dev,
> + struct amdxdna_drm_create_bo *args, struct drm_file *filp);
>
> int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo);
> int amdxdna_gem_pin(struct amdxdna_gem_obj *abo);
> diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
> index 5143b8c9b92b..d83be00daf2b 100644
> --- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
> +++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
> @@ -245,7 +245,7 @@ const struct drm_driver amdxdna_drm_drv = {
> .ioctls = amdxdna_drm_ioctls,
> .num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),
>
> - .gem_create_object = amdxdna_gem_create_object_cb,
> + .gem_create_object = amdxdna_gem_create_shmem_object_cb,
> .gem_prime_import = amdxdna_gem_prime_import,
> };
>
> diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.c b/drivers/accel/amdxdna/amdxdna_ubuf.c
> index fb71d6e3f44d..fb999aa25318 100644
> --- a/drivers/accel/amdxdna/amdxdna_ubuf.c
> +++ b/drivers/accel/amdxdna/amdxdna_ubuf.c
> @@ -17,7 +17,6 @@
> struct amdxdna_ubuf_priv {
> struct page **pages;
> u64 nr_pages;
> - enum amdxdna_ubuf_flag flags;
> struct mm_struct *mm;
> };
>
> @@ -37,11 +36,9 @@ static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
> if (ret)
> goto err_free_sg;
>
> - if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) {
> - ret = dma_map_sgtable(attach->dev, sg, direction, 0);
> - if (ret)
> - goto err_free_table;
> - }
> + ret = dma_map_sgtable(attach->dev, sg, direction, 0);
> + if (ret)
> + goto err_free_table;
>
> return sg;
>
> @@ -56,11 +53,7 @@ static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
> struct sg_table *sg,
> enum dma_data_direction direction)
> {
> - struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
> -
> - if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA)
> - dma_unmap_sgtable(attach->dev, sg, direction, 0);
> -
> + dma_unmap_sgtable(attach->dev, sg, direction, 0);
> sg_free_table(sg);
> kfree(sg);
> }
> @@ -133,7 +126,6 @@ static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
> };
>
> struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
> - enum amdxdna_ubuf_flag flags,
> u32 num_entries, void __user *va_entries)
> {
> struct amdxdna_dev *xdna = to_xdna_dev(dev);
> @@ -152,7 +144,6 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
> if (!ubuf)
> return ERR_PTR(-ENOMEM);
>
> - ubuf->flags = flags;
> ubuf->mm = current->mm;
> mmgrab(ubuf->mm);
>
> diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.h b/drivers/accel/amdxdna/amdxdna_ubuf.h
> index e5cb3bdb3ec9..8900a6dc4371 100644
> --- a/drivers/accel/amdxdna/amdxdna_ubuf.h
> +++ b/drivers/accel/amdxdna/amdxdna_ubuf.h
> @@ -8,12 +8,7 @@
> #include <drm/drm_device.h>
> #include <linux/dma-buf.h>
>
> -enum amdxdna_ubuf_flag {
> - AMDXDNA_UBUF_FLAG_MAP_DMA = 1,
> -};
> -
> struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
> - enum amdxdna_ubuf_flag flags,
> u32 num_entries, void __user *va_entries);
>
> #endif /* _AMDXDNA_UBUF_H_ */
> diff --git a/include/uapi/drm/amdxdna_accel.h b/include/uapi/drm/amdxdna_accel.h
> index 5bd13f4435f5..bddaaaf945cf 100644
> --- a/include/uapi/drm/amdxdna_accel.h
> +++ b/include/uapi/drm/amdxdna_accel.h
> @@ -156,10 +156,11 @@ struct amdxdna_drm_config_hwctx {
>
> enum amdxdna_bo_type {
> AMDXDNA_BO_INVALID = 0,
> - AMDXDNA_BO_SHMEM,
> - AMDXDNA_BO_DEV_HEAP,
> - AMDXDNA_BO_DEV,
> - AMDXDNA_BO_CMD,
> + AMDXDNA_BO_SHMEM = 1, /* Be compatible with legacy application code. */
> + AMDXDNA_BO_SHARE = 1,
> + AMDXDNA_BO_DEV_HEAP = 2,
> + AMDXDNA_BO_DEV = 3,
> + AMDXDNA_BO_CMD = 4,
> };
>
> /**
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval
2026-03-20 21:46 ` Mario Limonciello (AMD) (kernel.org)
@ 2026-03-21 5:26 ` Lizhi Hou
0 siblings, 0 replies; 5+ messages in thread
From: Lizhi Hou @ 2026-03-21 5:26 UTC (permalink / raw)
To: Mario Limonciello (AMD) (kernel.org), ogabbay, quic_jhugo,
dri-devel, maciej.falkowski
Cc: Max Zhen, linux-kernel, sonal.santan
On 3/20/26 14:46, Mario Limonciello (AMD) (kernel.org) wrote:
>
>
> On 3/20/2026 4:06 PM, Lizhi Hou wrote:
>> From: Max Zhen <max.zhen@amd.com>
>>
>> Refactor amdxdna GEM buffer object (BO) handling to simplify address
>> management and unify BO type semantics.
>>
>> Introduce helper APIs to retrieve commonly used BO addresses:
>> - User virtual address (UVA)
>> - Kernel virtual address (KVA)
>> - Device address (IOVA/PA)
>>
>> These helpers centralize address lookup logic and avoid duplicating
>> BO-specific handling across submission and execution paths. This also
>> improves readability and reduces the risk of inconsistent address
>> handling in future changes.
>>
>> As part of the refactor:
>> - Rename SHMEM BO type to SHARE to better reflect its usage.
>> - Merge CMD BO handling into SHARE, removing special-case logic for
>> command buffers.
>> - Consolidate BO type handling paths to reduce code duplication and
>> simplify maintenance.
>>
>> No functional change is intended. The refactor prepares the driver for
>> future enhancements by providing a cleaner abstraction for BO address
>> management.
>>
>> Signed-off-by: Max Zhen <max.zhen@amd.com>
> You forgot to include your S-o-b in the bump. Please include it when
> committing.
>
> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Thanks. Applied to drm-misc-next
>
>> ---
>> drivers/accel/amdxdna/aie2_ctx.c | 8 +-
>> drivers/accel/amdxdna/aie2_message.c | 33 +-
>> drivers/accel/amdxdna/amdxdna_ctx.c | 23 +-
>> drivers/accel/amdxdna/amdxdna_ctx.h | 15 +-
>> drivers/accel/amdxdna/amdxdna_gem.c | 400 +++++++++++-------------
>> drivers/accel/amdxdna/amdxdna_gem.h | 32 +-
>> drivers/accel/amdxdna/amdxdna_pci_drv.c | 2 +-
>> drivers/accel/amdxdna/amdxdna_ubuf.c | 17 +-
>> drivers/accel/amdxdna/amdxdna_ubuf.h | 5 -
>> include/uapi/drm/amdxdna_accel.h | 9 +-
>> 10 files changed, 266 insertions(+), 278 deletions(-)
>>
>> diff --git a/drivers/accel/amdxdna/aie2_ctx.c
>> b/drivers/accel/amdxdna/aie2_ctx.c
>> index 6292349868c5..66dbbfd322a2 100644
>> --- a/drivers/accel/amdxdna/aie2_ctx.c
>> +++ b/drivers/accel/amdxdna/aie2_ctx.c
>> @@ -79,7 +79,7 @@ static int aie2_hwctx_restart(struct amdxdna_dev
>> *xdna, struct amdxdna_hwctx *hw
>> }
>> ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
>> - amdxdna_obj_dma_addr(hwctx->client, heap),
>> + amdxdna_obj_dma_addr(heap),
>> heap->mem.size);
>> if (ret) {
>> XDNA_ERR(xdna, "Map host buf failed, ret %d", ret);
>> @@ -659,14 +659,14 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
>> .size = MAX_CHAIN_CMDBUF_SIZE,
>> };
>> - abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args,
>> client->filp);
>> + abo = amdxdna_drm_create_dev_bo(&xdna->ddev, &args,
>> client->filp);
>> if (IS_ERR(abo)) {
>> ret = PTR_ERR(abo);
>> goto free_cmd_bufs;
>> }
>> XDNA_DBG(xdna, "Command buf %d addr 0x%llx size 0x%lx",
>> - i, abo->mem.dev_addr, abo->mem.size);
>> + i, amdxdna_gem_dev_addr(abo), abo->mem.size);
>> priv->cmd_buf[i] = abo;
>> }
>> @@ -707,7 +707,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
>> }
>> ret = aie2_map_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
>> - amdxdna_obj_dma_addr(hwctx->client, heap),
>> + amdxdna_obj_dma_addr(heap),
>> heap->mem.size);
>> if (ret) {
>> XDNA_ERR(xdna, "Map host buffer failed, ret %d", ret);
>> diff --git a/drivers/accel/amdxdna/aie2_message.c
>> b/drivers/accel/amdxdna/aie2_message.c
>> index 4ec591306854..6e3fb52aa35f 100644
>> --- a/drivers/accel/amdxdna/aie2_message.c
>> +++ b/drivers/accel/amdxdna/aie2_message.c
>> @@ -548,10 +548,10 @@ int aie2_config_cu(struct amdxdna_hwctx *hwctx,
>> }
>> req.cfgs[i] = FIELD_PREP(AIE2_MSG_CFG_CU_PDI_ADDR,
>> - abo->mem.dev_addr >> shift);
>> + amdxdna_gem_dev_addr(abo) >> shift);
>> req.cfgs[i] |= FIELD_PREP(AIE2_MSG_CFG_CU_FUNC, cu->cu_func);
>> XDNA_DBG(xdna, "CU %d full addr 0x%llx, cfg 0x%x", i,
>> - abo->mem.dev_addr, req.cfgs[i]);
>> + amdxdna_gem_dev_addr(abo), req.cfgs[i]);
>> drm_gem_object_put(gobj);
>> }
>> req.num_cus = hwctx->cus->num_cus;
>> @@ -998,6 +998,7 @@ int aie2_cmdlist_multi_execbuf(struct
>> amdxdna_hwctx *hwctx,
>> struct mailbox_channel *chann = hwctx->priv->mbox_chann;
>> struct amdxdna_client *client = hwctx->client;
>> struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
>> + void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_cmd_chain *payload;
>> struct xdna_mailbox_msg msg;
>> @@ -1009,6 +1010,9 @@ int aie2_cmdlist_multi_execbuf(struct
>> amdxdna_hwctx *hwctx,
>> u32 op;
>> u32 i;
>> + if (!cmd_buf)
>> + return -ENOMEM;
>> +
>> op = amdxdna_cmd_get_op(cmd_abo);
>> payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len);
>> if (op != ERT_CMD_CHAIN) {
>> @@ -1032,15 +1036,14 @@ int aie2_cmdlist_multi_execbuf(struct
>> amdxdna_hwctx *hwctx,
>> u32 boh = (u32)(payload->data[i]);
>> struct amdxdna_gem_obj *abo;
>> - abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_CMD);
>> + abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_SHMEM);
>> if (!abo) {
>> XDNA_ERR(xdna, "Failed to find cmd BO %d", boh);
>> return -ENOENT;
>> }
>> size = cmdbuf_abo->mem.size - offset;
>> - ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva + offset,
>> - abo, &size, &op);
>> + ret = aie2_cmdlist_fill_slot(cmd_buf + offset, abo, &size,
>> &op);
>> amdxdna_gem_put_obj(abo);
>> if (ret)
>> return ret;
>> @@ -1050,16 +1053,16 @@ int aie2_cmdlist_multi_execbuf(struct
>> amdxdna_hwctx *hwctx,
>> XDNA_DBG(xdna, "Total %d commands:", ccnt);
>> print_hex_dump_debug("cmdbufs: ", DUMP_PREFIX_OFFSET, 16, 4,
>> - cmdbuf_abo->mem.kva, offset, false);
>> + cmd_buf, offset, false);
>> msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
>> if (msg.opcode == MSG_OP_MAX_OPCODE)
>> return -EOPNOTSUPP;
>> /* The offset is the accumulated total size of the cmd buffer */
>> - EXEC_MSG_OPS(xdna)->init_chain_req(&req, cmdbuf_abo->mem.dev_addr,
>> + EXEC_MSG_OPS(xdna)->init_chain_req(&req,
>> amdxdna_gem_dev_addr(cmdbuf_abo),
>> offset, ccnt);
>> - drm_clflush_virt_range(cmdbuf_abo->mem.kva, offset);
>> + drm_clflush_virt_range(cmd_buf, offset);
>> msg.handle = job;
>> msg.notify_cb = notify_cb;
>> @@ -1084,27 +1087,29 @@ int aie2_cmdlist_single_execbuf(struct
>> amdxdna_hwctx *hwctx,
>> struct mailbox_channel *chann = hwctx->priv->mbox_chann;
>> struct amdxdna_dev *xdna = hwctx->client->xdna;
>> struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
>> + void *cmd_buf = amdxdna_gem_vmap(cmdbuf_abo);
>> struct xdna_mailbox_msg msg;
>> union exec_chain_req req;
>> u32 op = ERT_INVALID_CMD;
>> size_t size;
>> int ret;
>> + if (!cmd_buf)
>> + return -ENOMEM;
>> +
>> size = cmdbuf_abo->mem.size;
>> - ret = aie2_cmdlist_fill_slot(cmdbuf_abo->mem.kva, cmd_abo,
>> &size, &op);
>> + ret = aie2_cmdlist_fill_slot(cmd_buf, cmd_abo, &size, &op);
>> if (ret)
>> return ret;
>> - print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4,
>> - cmdbuf_abo->mem.kva, size, false);
>> + print_hex_dump_debug("cmdbuf: ", DUMP_PREFIX_OFFSET, 16, 4,
>> cmd_buf, size, false);
>> msg.opcode = EXEC_MSG_OPS(xdna)->get_chain_msg_op(op);
>> if (msg.opcode == MSG_OP_MAX_OPCODE)
>> return -EOPNOTSUPP;
>> - EXEC_MSG_OPS(xdna)->init_chain_req(&req,
>> cmdbuf_abo->mem.dev_addr,
>> - size, 1);
>> - drm_clflush_virt_range(cmdbuf_abo->mem.kva, size);
>> + EXEC_MSG_OPS(xdna)->init_chain_req(&req,
>> amdxdna_gem_dev_addr(cmdbuf_abo), size, 1);
>> + drm_clflush_virt_range(cmd_buf, size);
>> msg.handle = job;
>> msg.notify_cb = notify_cb;
>> diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c
>> b/drivers/accel/amdxdna/amdxdna_ctx.c
>> index 4b921715176d..94e5639adc64 100644
>> --- a/drivers/accel/amdxdna/amdxdna_ctx.c
>> +++ b/drivers/accel/amdxdna/amdxdna_ctx.c
>> @@ -94,9 +94,12 @@ int amdxdna_hwctx_walk(struct amdxdna_client
>> *client, void *arg,
>> void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32
>> *size)
>> {
>> - struct amdxdna_cmd *cmd = abo->mem.kva;
>> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>> u32 num_masks, count;
>> + if (!cmd)
>> + return NULL;
>> +
>> if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
>> num_masks = 0;
>> else
>> @@ -118,10 +121,13 @@ void *amdxdna_cmd_get_payload(struct
>> amdxdna_gem_obj *abo, u32 *size)
>> u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo)
>> {
>> - struct amdxdna_cmd *cmd = abo->mem.kva;
>> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>> u32 num_masks, i;
>> u32 *cu_mask;
>> + if (!cmd)
>> + return INVALID_CU_IDX;
>> +
>> if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN)
>> return INVALID_CU_IDX;
>> @@ -141,19 +147,24 @@ int amdxdna_cmd_set_error(struct
>> amdxdna_gem_obj *abo,
>> void *err_data, size_t size)
>> {
>> struct amdxdna_client *client = job->hwctx->client;
>> - struct amdxdna_cmd *cmd = abo->mem.kva;
>> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>> struct amdxdna_cmd_chain *cc = NULL;
>> + if (!cmd)
>> + return -ENOMEM;
>> +
>> cmd->header &= ~AMDXDNA_CMD_STATE;
>> cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
>> if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) {
>> cc = amdxdna_cmd_get_payload(abo, NULL);
>> cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0;
>> - abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD);
>> + abo = amdxdna_gem_get_obj(client, cc->data[0],
>> AMDXDNA_BO_SHMEM);
>> if (!abo)
>> return -EINVAL;
>> - cmd = abo->mem.kva;
>> + cmd = amdxdna_gem_vmap(abo);
>> + if (!cmd)
>> + return -ENOMEM;
>> }
>> memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd));
>> @@ -472,7 +483,7 @@ int amdxdna_cmd_submit(struct amdxdna_client
>> *client,
>> job->drv_cmd = drv_cmd;
>> if (cmd_bo_hdl != AMDXDNA_INVALID_BO_HANDLE) {
>> - job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl,
>> AMDXDNA_BO_CMD);
>> + job->cmd_bo = amdxdna_gem_get_obj(client, cmd_bo_hdl,
>> AMDXDNA_BO_SHMEM);
>> if (!job->cmd_bo) {
>> XDNA_ERR(xdna, "Failed to get cmd bo from %d",
>> cmd_bo_hdl);
>> ret = -EINVAL;
>> diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h
>> b/drivers/accel/amdxdna/amdxdna_ctx.h
>> index 57db1527a93b..a8557d7e8923 100644
>> --- a/drivers/accel/amdxdna/amdxdna_ctx.h
>> +++ b/drivers/accel/amdxdna/amdxdna_ctx.h
>> @@ -158,7 +158,10 @@ struct amdxdna_sched_job {
>> static inline u32
>> amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
>> {
>> - struct amdxdna_cmd *cmd = abo->mem.kva;
>> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>> +
>> + if (!cmd)
>> + return ERT_INVALID_CMD;
>> return FIELD_GET(AMDXDNA_CMD_OPCODE, cmd->header);
>> }
>> @@ -166,7 +169,10 @@ amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
>> static inline void
>> amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum
>> ert_cmd_state s)
>> {
>> - struct amdxdna_cmd *cmd = abo->mem.kva;
>> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>> +
>> + if (!cmd)
>> + return;
>> cmd->header &= ~AMDXDNA_CMD_STATE;
>> cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, s);
>> @@ -175,7 +181,10 @@ amdxdna_cmd_set_state(struct amdxdna_gem_obj
>> *abo, enum ert_cmd_state s)
>> static inline enum ert_cmd_state
>> amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo)
>> {
>> - struct amdxdna_cmd *cmd = abo->mem.kva;
>> + struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo);
>> +
>> + if (!cmd)
>> + return ERT_CMD_STATE_INVALID;
>> return FIELD_GET(AMDXDNA_CMD_STATE, cmd->header);
>> }
>> diff --git a/drivers/accel/amdxdna/amdxdna_gem.c
>> b/drivers/accel/amdxdna/amdxdna_gem.c
>> index d80cf164740c..3c15d06b6048 100644
>> --- a/drivers/accel/amdxdna/amdxdna_gem.c
>> +++ b/drivers/accel/amdxdna/amdxdna_gem.c
>> @@ -30,7 +30,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_mem *mem = &abo->mem;
>> struct amdxdna_gem_obj *heap;
>> - u64 offset;
>> u32 align;
>> int ret;
>> @@ -42,7 +41,7 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
>> goto unlock_out;
>> }
>> - if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) {
>> + if (amdxdna_gem_uva(heap) == AMDXDNA_INVALID_ADDR) {
>> XDNA_ERR(xdna, "Invalid dev heap userptr");
>> ret = -EINVAL;
>> goto unlock_out;
>> @@ -64,11 +63,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
>> goto unlock_out;
>> }
>> - mem->dev_addr = abo->mm_node.start;
>> - 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:
>> @@ -77,13 +71,6 @@ amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo)
>> 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)
>> {
>> @@ -99,6 +86,105 @@ amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo)
>> mutex_unlock(&abo->client->mm_lock);
>> }
>> +static struct amdxdna_gem_obj *
>> +amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
>> +{
>> + struct amdxdna_gem_obj *abo;
>> +
>> + abo = kzalloc_obj(*abo);
>> + if (!abo)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + abo->pinned = false;
>> + abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
>> + mutex_init(&abo->lock);
>> +
>> + abo->mem.dma_addr = AMDXDNA_INVALID_ADDR;
>> + abo->mem.uva = AMDXDNA_INVALID_ADDR;
>> + abo->mem.size = size;
>> + INIT_LIST_HEAD(&abo->mem.umap_list);
>> +
>> + return abo;
>> +}
>> +
>> +static void
>> +amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
>> +{
>> + mutex_destroy(&abo->lock);
>> + kfree(abo);
>> +}
>> +
>> +/*
>> + * Obtains a kernel virtual address on the BO (usually of small size).
>> + * The mapping is established on the first call and stays valid until
>> + * amdxdna_gem_vunmap() is called.
>> + */
>> +void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
>> +{
>> + struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
>> + int ret;
>> +
>> + if (abo->mem.kva)
>> + return abo->mem.kva;
>> +
>> + /* The first call to get the kva, taking slow path. */
>> + guard(mutex)(&abo->lock);
>> +
>> + if (!abo->mem.kva) {
>> + ret = drm_gem_vmap(to_gobj(abo), &map);
>> + if (ret)
>> + XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
>> + else
>> + abo->mem.kva = map.vaddr;
>> + }
>> + return abo->mem.kva;
>> +}
>> +
>> +/*
>> + * Free mapping established through amdxdna_gem_vmap()
>> + */
>> +static void amdxdna_gem_vunmap(struct amdxdna_gem_obj *abo)
>> +{
>> + guard(mutex)(&abo->lock);
>> +
>> + if (abo->mem.kva) {
>> + struct iosys_map map = IOSYS_MAP_INIT_VADDR(abo->mem.kva);
>> +
>> + drm_gem_vunmap(to_gobj(abo), &map);
>> + abo->mem.kva = NULL;
>> + }
>> +}
>> +
>> +/*
>> + * Obtain the user virtual address for accessing the BO.
>> + * It can be used for device to access the BO when PASID is enabled.
>> + */
>> +u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo)
>> +{
>> + if (abo->type == AMDXDNA_BO_DEV) {
>> + struct amdxdna_gem_obj *heap = abo->client->dev_heap;
>> + u64 off = amdxdna_dev_bo_offset(abo);
>> +
>> + if (amdxdna_gem_uva(heap) != AMDXDNA_INVALID_ADDR)
>> + return amdxdna_gem_uva(heap) + off;
>> + return AMDXDNA_INVALID_ADDR;
>> + }
>> +
>> + return abo->mem.uva;
>> +}
>> +
>> +/*
>> + * Obtain the address for device to access the BO.
>> + */
>> +u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo)
>> +{
>> + if (abo->type == AMDXDNA_BO_DEV_HEAP)
>> + return abo->client->xdna->dev_info->dev_mem_base;
>> + if (abo->type == AMDXDNA_BO_DEV)
>> + return abo->mm_node.start;
>> + return amdxdna_obj_dma_addr(abo);
>> +}
>> +
>> static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
>> const struct mmu_notifier_range *range,
>> unsigned long cur_seq)
>> @@ -161,16 +247,19 @@ static void amdxdna_hmm_unregister(struct
>> amdxdna_gem_obj *abo,
>> static void amdxdna_umap_release(struct kref *ref)
>> {
>> struct amdxdna_umap *mapp = container_of(ref, struct
>> amdxdna_umap, refcnt);
>> + struct amdxdna_gem_obj *abo = mapp->abo;
>> struct vm_area_struct *vma = mapp->vma;
>> struct amdxdna_dev *xdna;
>> mmu_interval_notifier_remove(&mapp->notifier);
>> - if (is_import_bo(mapp->abo) && vma->vm_file &&
>> vma->vm_file->f_mapping)
>> + if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
>> mapping_clear_unevictable(vma->vm_file->f_mapping);
>> xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
>> down_write(&xdna->notifier_lock);
>> list_del(&mapp->node);
>> + if (list_empty(&abo->mem.umap_list))
>> + abo->mem.uva = AMDXDNA_INVALID_ADDR;
>> up_write(&xdna->notifier_lock);
>> kvfree(mapp->range.hmm_pfns);
>> @@ -232,13 +321,13 @@ static int amdxdna_hmm_register(struct
>> amdxdna_gem_obj *abo,
>> mapp->abo = abo;
>> kref_init(&mapp->refcnt);
>> - if (abo->mem.userptr == AMDXDNA_INVALID_ADDR)
>> - abo->mem.userptr = addr;
>> INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
>> if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
>> mapping_set_unevictable(vma->vm_file->f_mapping);
>> down_write(&xdna->notifier_lock);
>> + if (list_empty(&abo->mem.umap_list))
>> + abo->mem.uva = addr;
>> list_add_tail(&mapp->node, &abo->mem.umap_list);
>> up_write(&xdna->notifier_lock);
>> @@ -256,10 +345,11 @@ 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);
>> + XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type,
>> amdxdna_gem_dev_addr(abo));
>> if (abo->pinned)
>> amdxdna_gem_unpin(abo);
>> + amdxdna_gem_vunmap(abo);
>> amdxdna_gem_heap_free(abo);
>> drm_gem_object_release(gobj);
>> amdxdna_gem_destroy_obj(abo);
>> @@ -390,35 +480,6 @@ static const struct dma_buf_ops
>> amdxdna_dmabuf_ops = {
>> .vunmap = drm_gem_dmabuf_vunmap,
>> };
>> -static int amdxdna_gem_obj_vmap(struct amdxdna_gem_obj *abo, void
>> **vaddr)
>> -{
>> - struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
>> - int ret;
>> -
>> - if (is_import_bo(abo))
>> - ret = dma_buf_vmap_unlocked(abo->dma_buf, &map);
>> - else
>> - ret = drm_gem_vmap(to_gobj(abo), &map);
>> -
>> - *vaddr = map.vaddr;
>> - return ret;
>> -}
>> -
>> -static void amdxdna_gem_obj_vunmap(struct amdxdna_gem_obj *abo)
>> -{
>> - struct iosys_map map;
>> -
>> - if (!abo->mem.kva)
>> - return;
>> -
>> - iosys_map_set_vaddr(&map, abo->mem.kva);
>> -
>> - if (is_import_bo(abo))
>> - dma_buf_vunmap_unlocked(abo->dma_buf, &map);
>> - else
>> - drm_gem_vunmap(to_gobj(abo), &map);
>> -}
>> -
>> static struct dma_buf *amdxdna_gem_prime_export(struct
>> drm_gem_object *gobj, int flags)
>> {
>> struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
>> @@ -452,7 +513,7 @@ static void amdxdna_gem_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);
>> + XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type,
>> amdxdna_gem_dev_addr(abo));
>> amdxdna_hmm_unregister(abo, NULL);
>> flush_workqueue(xdna->notifier_wq);
>> @@ -463,15 +524,16 @@ static void amdxdna_gem_obj_free(struct
>> drm_gem_object *gobj)
>> if (abo->type == AMDXDNA_BO_DEV_HEAP)
>> drm_mm_takedown(&abo->mm);
>> - amdxdna_gem_obj_vunmap(abo);
>> + if (amdxdna_iova_on(xdna))
>> + amdxdna_iommu_unmap_bo(xdna, abo);
>> +
>> + amdxdna_gem_vunmap(abo);
>> mutex_destroy(&abo->lock);
>> - if (is_import_bo(abo)) {
>> + if (is_import_bo(abo))
>> amdxdna_imported_obj_free(abo);
>> - return;
>> - }
>> -
>> - drm_gem_shmem_free(&abo->base);
>> + else
>> + drm_gem_shmem_free(&abo->base);
>> }
>> static int amdxdna_gem_obj_open(struct drm_gem_object *gobj,
>> struct drm_file *filp)
>> @@ -481,43 +543,38 @@ static int amdxdna_gem_obj_open(struct
>> drm_gem_object *gobj, struct drm_file *fi
>> int ret;
>> guard(mutex)(&abo->lock);
>> - if (abo->ref) {
>> - abo->ref++;
>> - return 0;
>> - }
>> + if (!abo->client)
>> + abo->client = filp->driver_priv;
>> if (amdxdna_iova_on(xdna)) {
>> ret = amdxdna_iommu_map_bo(xdna, abo);
>> if (ret)
>> return ret;
>> }
>> - abo->ref++;
>> return 0;
>> }
>> -static void amdxdna_gem_obj_close(struct drm_gem_object *gobj,
>> struct drm_file *filp)
>> +static int amdxdna_gem_dev_obj_vmap(struct drm_gem_object *obj,
>> struct iosys_map *map)
>> {
>> - struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev);
>> - struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
>> + struct amdxdna_gem_obj *abo = to_xdna_obj(obj);
>> + void *base = amdxdna_gem_vmap(abo->client->dev_heap);
>> + u64 offset = amdxdna_dev_bo_offset(abo);
>> - guard(mutex)(&abo->lock);
>> - abo->ref--;
>> - if (abo->ref)
>> - return;
>> -
>> - if (amdxdna_iova_on(xdna))
>> - amdxdna_iommu_unmap_bo(xdna, abo);
>> + if (!base)
>> + return -ENOMEM;
>> + iosys_map_set_vaddr(map, base + offset);
>> + return 0;
>> }
>> static const struct drm_gem_object_funcs
>> amdxdna_gem_dev_obj_funcs = {
>> .free = amdxdna_gem_dev_obj_free,
>> + .vmap = amdxdna_gem_dev_obj_vmap,
>> };
>> static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
>> .free = amdxdna_gem_obj_free,
>> .open = amdxdna_gem_obj_open,
>> - .close = amdxdna_gem_obj_close,
>> .print_info = drm_gem_shmem_object_print_info,
>> .pin = drm_gem_shmem_object_pin,
>> .unpin = drm_gem_shmem_object_unpin,
>> @@ -529,31 +586,9 @@ static const struct drm_gem_object_funcs
>> amdxdna_gem_shmem_funcs = {
>> .export = amdxdna_gem_prime_export,
>> };
>> -static struct amdxdna_gem_obj *
>> -amdxdna_gem_create_obj(struct drm_device *dev, size_t size)
>> -{
>> - struct amdxdna_gem_obj *abo;
>> -
>> - abo = kzalloc_obj(*abo);
>> - if (!abo)
>> - return ERR_PTR(-ENOMEM);
>> -
>> - abo->pinned = false;
>> - abo->assigned_hwctx = AMDXDNA_INVALID_CTX_HANDLE;
>> - mutex_init(&abo->lock);
>> -
>> - abo->mem.userptr = AMDXDNA_INVALID_ADDR;
>> - abo->mem.dev_addr = AMDXDNA_INVALID_ADDR;
>> - abo->mem.dma_addr = AMDXDNA_INVALID_ADDR;
>> - abo->mem.size = size;
>> - INIT_LIST_HEAD(&abo->mem.umap_list);
>> -
>> - return abo;
>> -}
>> -
>> /* For drm_driver->gem_create_object callback */
>> struct drm_gem_object *
>> -amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
>> +amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t size)
>> {
>> struct amdxdna_gem_obj *abo;
>> @@ -567,8 +602,9 @@ amdxdna_gem_create_object_cb(struct drm_device
>> *dev, size_t size)
>> }
>> static struct amdxdna_gem_obj *
>> -amdxdna_gem_create_shmem_object(struct drm_device *dev, size_t size)
>> +amdxdna_gem_create_shmem_object(struct drm_device *dev, struct
>> amdxdna_drm_create_bo *args)
>> {
>> + size_t size = args->size;
>> struct drm_gem_shmem_object *shmem = drm_gem_shmem_create(dev,
>> size);
>> if (IS_ERR(shmem))
>> @@ -582,7 +618,6 @@ static struct amdxdna_gem_obj *
>> amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct
>> amdxdna_drm_create_bo *args)
>> {
>> struct amdxdna_dev *xdna = to_xdna_dev(dev);
>> - enum amdxdna_ubuf_flag flags = 0;
>> struct amdxdna_drm_va_tbl va_tbl;
>> struct drm_gem_object *gobj;
>> struct dma_buf *dma_buf;
>> @@ -593,10 +628,7 @@ amdxdna_gem_create_ubuf_object(struct drm_device
>> *dev, struct amdxdna_drm_create
>> }
>> if (va_tbl.num_entries) {
>> - if (args->type == AMDXDNA_BO_CMD)
>> - flags |= AMDXDNA_UBUF_FLAG_MAP_DMA;
>> -
>> - dma_buf = amdxdna_get_ubuf(dev, flags, va_tbl.num_entries,
>> + dma_buf = amdxdna_get_ubuf(dev, va_tbl.num_entries,
>> u64_to_user_ptr(args->vaddr + sizeof(va_tbl)));
>> } else {
>> dma_buf = dma_buf_get(va_tbl.dmabuf_fd);
>> @@ -616,18 +648,6 @@ amdxdna_gem_create_ubuf_object(struct drm_device
>> *dev, struct amdxdna_drm_create
>> return to_xdna_obj(gobj);
>> }
>> -static struct amdxdna_gem_obj *
>> -amdxdna_gem_create_object(struct drm_device *dev,
>> - struct amdxdna_drm_create_bo *args)
>> -{
>> - size_t aligned_sz = PAGE_ALIGN(args->size);
>> -
>> - if (args->vaddr)
>> - return amdxdna_gem_create_ubuf_object(dev, args);
>> -
>> - return amdxdna_gem_create_shmem_object(dev, aligned_sz);
>> -}
>> -
>> struct drm_gem_object *
>> amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf
>> *dma_buf)
>> {
>> @@ -660,7 +680,8 @@ amdxdna_gem_prime_import(struct drm_device *dev,
>> struct dma_buf *dma_buf)
>> abo = to_xdna_obj(gobj);
>> abo->attach = attach;
>> abo->dma_buf = dma_buf;
>> - abo->type = AMDXDNA_BO_SHMEM;
>> + abo->type = AMDXDNA_BO_SHARE;
>> + gobj->resv = dma_buf->resv;
>> return gobj;
>> @@ -675,92 +696,92 @@ amdxdna_gem_prime_import(struct drm_device
>> *dev, struct dma_buf *dma_buf)
>> }
>> static struct amdxdna_gem_obj *
>> -amdxdna_drm_alloc_shmem(struct drm_device *dev,
>> - struct amdxdna_drm_create_bo *args,
>> - struct drm_file *filp)
>> +amdxdna_drm_create_share_bo(struct drm_device *dev,
>> + struct amdxdna_drm_create_bo *args, struct drm_file
>> *filp)
>> {
>> - struct amdxdna_client *client = filp->driver_priv;
>> struct amdxdna_gem_obj *abo;
>> - abo = amdxdna_gem_create_object(dev, args);
>> + if (args->vaddr)
>> + abo = amdxdna_gem_create_ubuf_object(dev, args);
>> + else
>> + abo = amdxdna_gem_create_shmem_object(dev, args);
>> if (IS_ERR(abo))
>> return ERR_CAST(abo);
>> - abo->client = client;
>> - abo->type = AMDXDNA_BO_SHMEM;
>> + if (args->type == AMDXDNA_BO_DEV_HEAP)
>> + abo->type = AMDXDNA_BO_DEV_HEAP;
>> + else
>> + abo->type = AMDXDNA_BO_SHARE;
>> return abo;
>> }
>> static struct amdxdna_gem_obj *
>> -amdxdna_drm_create_dev_heap(struct drm_device *dev,
>> - struct amdxdna_drm_create_bo *args,
>> - struct drm_file *filp)
>> +amdxdna_drm_create_dev_heap_bo(struct drm_device *dev,
>> + struct amdxdna_drm_create_bo *args, struct
>> drm_file *filp)
>> {
>> struct amdxdna_client *client = filp->driver_priv;
>> struct amdxdna_dev *xdna = to_xdna_dev(dev);
>> struct amdxdna_gem_obj *abo;
>> int ret;
>> - if (args->size > xdna->dev_info->dev_mem_size) {
>> - XDNA_DBG(xdna, "Invalid dev heap size 0x%llx, limit 0x%lx",
>> + WARN_ON(!is_power_of_2(xdna->dev_info->dev_mem_size));
>> + XDNA_DBG(xdna, "Requested dev heap size 0x%llx", args->size);
>> + if (!args->size || !IS_ALIGNED(args->size,
>> xdna->dev_info->dev_mem_size)) {
>> + XDNA_ERR(xdna, "The dev heap size 0x%llx is not multiple of
>> 0x%lx",
>> args->size, xdna->dev_info->dev_mem_size);
>> return ERR_PTR(-EINVAL);
>> }
>> + /* HEAP BO is a special case of SHMEM BO. */
>> + abo = amdxdna_drm_create_share_bo(dev, args, filp);
>> + if (IS_ERR(abo))
>> + return ERR_CAST(abo);
>> +
>> + /* Set up heap for this client. */
>> mutex_lock(&client->mm_lock);
>> +
>> if (client->dev_heap) {
>> XDNA_DBG(client->xdna, "dev heap is already created");
>> ret = -EBUSY;
>> goto mm_unlock;
>> }
>> -
>> - abo = amdxdna_gem_create_object(dev, args);
>> - if (IS_ERR(abo)) {
>> - ret = PTR_ERR(abo);
>> - goto mm_unlock;
>> - }
>> -
>> - 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 = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
>> - if (ret) {
>> - XDNA_ERR(xdna, "Vmap heap bo failed, ret %d", ret);
>> - goto release_obj;
>> - }
>> -
>> client->dev_heap = abo;
>> drm_gem_object_get(to_gobj(abo));
>> +
>> + drm_mm_init(&abo->mm, xdna->dev_info->dev_mem_base, abo->mem.size);
>> +
>> mutex_unlock(&client->mm_lock);
>> return abo;
>> -release_obj:
>> - drm_gem_object_put(to_gobj(abo));
>> mm_unlock:
>> mutex_unlock(&client->mm_lock);
>> + drm_gem_object_put(to_gobj(abo));
>> return ERR_PTR(ret);
>> }
>> struct amdxdna_gem_obj *
>> -amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
>> - struct amdxdna_drm_create_bo *args,
>> - struct drm_file *filp)
>> +amdxdna_drm_create_dev_bo(struct drm_device *dev,
>> + struct amdxdna_drm_create_bo *args, struct drm_file
>> *filp)
>> {
>> + size_t aligned_sz = PAGE_ALIGN(args->size);
>> 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;
>> + struct drm_gem_object *gobj;
>> int ret;
>> - abo = amdxdna_gem_create_obj(&xdna->ddev, aligned_sz);
>> + if (!aligned_sz) {
>> + XDNA_ERR(xdna, "Invalid BO size 0x%llx", args->size);
>> + return ERR_PTR(-EINVAL);
>> + }
>> +
>> + abo = amdxdna_gem_create_obj(dev, aligned_sz);
>> if (IS_ERR(abo))
>> return abo;
>> -
>> - to_gobj(abo)->funcs = &amdxdna_gem_dev_obj_funcs;
>> + gobj = to_gobj(abo);
>> + gobj->funcs = &amdxdna_gem_dev_obj_funcs;
>> abo->type = AMDXDNA_BO_DEV;
>> abo->client = client;
>> @@ -770,31 +791,7 @@ amdxdna_drm_alloc_dev_bo(struct drm_device *dev,
>> amdxdna_gem_destroy_obj(abo);
>> return ERR_PTR(ret);
>> }
>> -
>> - drm_gem_private_object_init(&xdna->ddev, to_gobj(abo), aligned_sz);
>> -
>> - return abo;
>> -}
>> -
>> -static struct amdxdna_gem_obj *
>> -amdxdna_drm_create_cmd_bo(struct drm_device *dev,
>> - struct amdxdna_drm_create_bo *args,
>> - struct drm_file *filp)
>> -{
>> - struct amdxdna_dev *xdna = to_xdna_dev(dev);
>> - struct amdxdna_gem_obj *abo;
>> -
>> - if (args->size < sizeof(struct amdxdna_cmd)) {
>> - XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
>> - return ERR_PTR(-EINVAL);
>> - }
>> -
>> - abo = amdxdna_gem_create_object(dev, args);
>> - if (IS_ERR(abo))
>> - return ERR_CAST(abo);
>> -
>> - abo->type = AMDXDNA_BO_CMD;
>> - abo->client = filp->driver_priv;
>> + drm_gem_private_object_init(dev, gobj, aligned_sz);
>> return abo;
>> }
>> @@ -812,17 +809,16 @@ int amdxdna_drm_create_bo_ioctl(struct
>> drm_device *dev, void *data, struct drm_f
>> XDNA_DBG(xdna, "BO arg type %d vaddr 0x%llx size 0x%llx flags
>> 0x%llx",
>> args->type, args->vaddr, args->size, args->flags);
>> switch (args->type) {
>> - case AMDXDNA_BO_SHMEM:
>> - abo = amdxdna_drm_alloc_shmem(dev, args, filp);
>> + case AMDXDNA_BO_CMD:
>> + fallthrough;
>> + case AMDXDNA_BO_SHARE:
>> + abo = amdxdna_drm_create_share_bo(dev, args, filp);
>> break;
>> case AMDXDNA_BO_DEV_HEAP:
>> - abo = amdxdna_drm_create_dev_heap(dev, args, filp);
>> + abo = amdxdna_drm_create_dev_heap_bo(dev, args, filp);
>> break;
>> case AMDXDNA_BO_DEV:
>> - abo = amdxdna_drm_alloc_dev_bo(dev, args, filp);
>> - break;
>> - case AMDXDNA_BO_CMD:
>> - abo = amdxdna_drm_create_cmd_bo(dev, args, filp);
>> + abo = amdxdna_drm_create_dev_bo(dev, args, filp);
>> break;
>> default:
>> return -EINVAL;
>> @@ -838,8 +834,8 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device
>> *dev, void *data, struct drm_f
>> }
>> XDNA_DBG(xdna, "BO hdl %d type %d userptr 0x%llx xdna_addr
>> 0x%llx size 0x%lx",
>> - args->handle, args->type, abo->mem.userptr,
>> - abo->mem.dev_addr, abo->mem.size);
>> + args->handle, args->type, amdxdna_gem_uva(abo),
>> + amdxdna_gem_dev_addr(abo), abo->mem.size);
>> put_obj:
>> /* Dereference object reference. Handle holds it now. */
>> drm_gem_object_put(to_gobj(abo));
>> @@ -890,38 +886,19 @@ void amdxdna_gem_unpin(struct amdxdna_gem_obj
>> *abo)
>> struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client
>> *client,
>> u32 bo_hdl, u8 bo_type)
>> {
>> - struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_gem_obj *abo;
>> struct drm_gem_object *gobj;
>> - int ret;
>> gobj = drm_gem_object_lookup(client->filp, bo_hdl);
>> if (!gobj) {
>> - XDNA_DBG(xdna, "Can not find bo %d", bo_hdl);
>> + XDNA_DBG(client->xdna, "Can not find bo %d", bo_hdl);
>> return NULL;
>> }
>> abo = to_xdna_obj(gobj);
>> - if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
>> - goto put_obj;
>> -
>> - if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
>> + if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
>> return abo;
>> - if (abo->mem.size > SZ_32K) {
>> - XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
>> - goto put_obj;
>> - }
>> -
>> - ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
>> - if (ret) {
>> - XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
>> - goto put_obj;
>> - }
>> -
>> - return abo;
>> -
>> -put_obj:
>> drm_gem_object_put(gobj);
>> return NULL;
>> }
>> @@ -944,11 +921,8 @@ int amdxdna_drm_get_bo_info_ioctl(struct
>> drm_device *dev, void *data, struct drm
>> }
>> abo = to_xdna_obj(gobj);
>> - args->vaddr = abo->mem.userptr;
>> - if (abo->mem.dev_addr != AMDXDNA_INVALID_ADDR)
>> - args->xdna_addr = abo->mem.dev_addr;
>> - else
>> - args->xdna_addr = abo->mem.dma_addr;
>> + args->vaddr = amdxdna_gem_uva(abo);
>> + args->xdna_addr = amdxdna_gem_dev_addr(abo);
>> if (abo->type != AMDXDNA_BO_DEV)
>> args->map_offset = drm_vma_node_offset_addr(&gobj->vma_node);
>> @@ -993,8 +967,8 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device
>> *dev,
>> if (is_import_bo(abo))
>> drm_clflush_sg(abo->base.sgt);
>> - else if (abo->mem.kva)
>> - drm_clflush_virt_range(abo->mem.kva + args->offset,
>> args->size);
>> + else if (amdxdna_gem_vmap(abo))
>> + drm_clflush_virt_range(amdxdna_gem_vmap(abo) + args->offset,
>> args->size);
>> else if (abo->base.pages)
>> drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT);
>> else
>> diff --git a/drivers/accel/amdxdna/amdxdna_gem.h
>> b/drivers/accel/amdxdna/amdxdna_gem.h
>> index fbeb622e7cf9..a77d9344f8a4 100644
>> --- a/drivers/accel/amdxdna/amdxdna_gem.h
>> +++ b/drivers/accel/amdxdna/amdxdna_gem.h
>> @@ -24,15 +24,16 @@ struct amdxdna_umap {
>> };
>> struct amdxdna_mem {
>> - u64 userptr;
>> void *kva;
>> - u64 dev_addr;
>> u64 dma_addr;
>> size_t size;
>> - struct page **pages;
>> - u32 nr_pages;
>> struct list_head umap_list;
>> bool map_invalid;
>> + /*
>> + * Cache the first mmap uva as PASID addr, which can be accessed
>> by driver
>> + * without taking notifier_lock.
>> + */
>> + u64 uva;
>> };
>> struct amdxdna_gem_obj {
>> @@ -40,11 +41,10 @@ struct amdxdna_gem_obj {
>> struct amdxdna_client *client;
>> u8 type;
>> bool pinned;
>> - struct mutex lock; /* Protects: pinned */
>> + struct mutex lock; /* Protects: pinned, mem.kva */
>> struct amdxdna_mem mem;
>> - u32 ref;
>> - /* Below members is uninitialized when needed */
>> + /* Below members are initialized when needed */
>> struct drm_mm mm; /* For AMDXDNA_BO_DEV_HEAP */
>> struct drm_mm_node mm_node; /* For AMDXDNA_BO_DEV */
>> u32 assigned_hwctx;
>> @@ -67,27 +67,29 @@ static inline void amdxdna_gem_put_obj(struct
>> amdxdna_gem_obj *abo)
>> drm_gem_object_put(to_gobj(abo));
>> }
>> +void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo);
>> +u64 amdxdna_gem_uva(struct amdxdna_gem_obj *abo);
>> +u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
>> +
>> static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
>> {
>> - return abo->mem.dev_addr - abo->client->dev_heap->mem.dev_addr;
>> + return amdxdna_gem_dev_addr(abo) -
>> amdxdna_gem_dev_addr(abo->client->dev_heap);
>> }
>> -static inline u64 amdxdna_obj_dma_addr(struct amdxdna_client *client,
>> - struct amdxdna_gem_obj *abo)
>> +static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
>> {
>> - return amdxdna_pasid_on(client) ? abo->mem.userptr :
>> abo->mem.dma_addr;
>> + return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) :
>> abo->mem.dma_addr;
>> }
>> void amdxdna_umap_put(struct amdxdna_umap *mapp);
>> struct drm_gem_object *
>> -amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size);
>> +amdxdna_gem_create_shmem_object_cb(struct drm_device *dev, size_t
>> size);
>> struct drm_gem_object *
>> 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);
>> +amdxdna_drm_create_dev_bo(struct drm_device *dev,
>> + struct amdxdna_drm_create_bo *args, struct drm_file
>> *filp);
>> int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo);
>> int amdxdna_gem_pin(struct amdxdna_gem_obj *abo);
>> diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c
>> b/drivers/accel/amdxdna/amdxdna_pci_drv.c
>> index 5143b8c9b92b..d83be00daf2b 100644
>> --- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
>> +++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
>> @@ -245,7 +245,7 @@ const struct drm_driver amdxdna_drm_drv = {
>> .ioctls = amdxdna_drm_ioctls,
>> .num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),
>> - .gem_create_object = amdxdna_gem_create_object_cb,
>> + .gem_create_object = amdxdna_gem_create_shmem_object_cb,
>> .gem_prime_import = amdxdna_gem_prime_import,
>> };
>> diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.c
>> b/drivers/accel/amdxdna/amdxdna_ubuf.c
>> index fb71d6e3f44d..fb999aa25318 100644
>> --- a/drivers/accel/amdxdna/amdxdna_ubuf.c
>> +++ b/drivers/accel/amdxdna/amdxdna_ubuf.c
>> @@ -17,7 +17,6 @@
>> struct amdxdna_ubuf_priv {
>> struct page **pages;
>> u64 nr_pages;
>> - enum amdxdna_ubuf_flag flags;
>> struct mm_struct *mm;
>> };
>> @@ -37,11 +36,9 @@ static struct sg_table *amdxdna_ubuf_map(struct
>> dma_buf_attachment *attach,
>> if (ret)
>> goto err_free_sg;
>> - if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) {
>> - ret = dma_map_sgtable(attach->dev, sg, direction, 0);
>> - if (ret)
>> - goto err_free_table;
>> - }
>> + ret = dma_map_sgtable(attach->dev, sg, direction, 0);
>> + if (ret)
>> + goto err_free_table;
>> return sg;
>> @@ -56,11 +53,7 @@ static void amdxdna_ubuf_unmap(struct
>> dma_buf_attachment *attach,
>> struct sg_table *sg,
>> enum dma_data_direction direction)
>> {
>> - struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
>> -
>> - if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA)
>> - dma_unmap_sgtable(attach->dev, sg, direction, 0);
>> -
>> + dma_unmap_sgtable(attach->dev, sg, direction, 0);
>> sg_free_table(sg);
>> kfree(sg);
>> }
>> @@ -133,7 +126,6 @@ static const struct dma_buf_ops
>> amdxdna_ubuf_dmabuf_ops = {
>> };
>> struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
>> - enum amdxdna_ubuf_flag flags,
>> u32 num_entries, void __user *va_entries)
>> {
>> struct amdxdna_dev *xdna = to_xdna_dev(dev);
>> @@ -152,7 +144,6 @@ struct dma_buf *amdxdna_get_ubuf(struct
>> drm_device *dev,
>> if (!ubuf)
>> return ERR_PTR(-ENOMEM);
>> - ubuf->flags = flags;
>> ubuf->mm = current->mm;
>> mmgrab(ubuf->mm);
>> diff --git a/drivers/accel/amdxdna/amdxdna_ubuf.h
>> b/drivers/accel/amdxdna/amdxdna_ubuf.h
>> index e5cb3bdb3ec9..8900a6dc4371 100644
>> --- a/drivers/accel/amdxdna/amdxdna_ubuf.h
>> +++ b/drivers/accel/amdxdna/amdxdna_ubuf.h
>> @@ -8,12 +8,7 @@
>> #include <drm/drm_device.h>
>> #include <linux/dma-buf.h>
>> -enum amdxdna_ubuf_flag {
>> - AMDXDNA_UBUF_FLAG_MAP_DMA = 1,
>> -};
>> -
>> struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
>> - enum amdxdna_ubuf_flag flags,
>> u32 num_entries, void __user *va_entries);
>> #endif /* _AMDXDNA_UBUF_H_ */
>> diff --git a/include/uapi/drm/amdxdna_accel.h
>> b/include/uapi/drm/amdxdna_accel.h
>> index 5bd13f4435f5..bddaaaf945cf 100644
>> --- a/include/uapi/drm/amdxdna_accel.h
>> +++ b/include/uapi/drm/amdxdna_accel.h
>> @@ -156,10 +156,11 @@ struct amdxdna_drm_config_hwctx {
>> enum amdxdna_bo_type {
>> AMDXDNA_BO_INVALID = 0,
>> - AMDXDNA_BO_SHMEM,
>> - AMDXDNA_BO_DEV_HEAP,
>> - AMDXDNA_BO_DEV,
>> - AMDXDNA_BO_CMD,
>> + AMDXDNA_BO_SHMEM = 1, /* Be compatible with legacy application
>> code. */
>> + AMDXDNA_BO_SHARE = 1,
>> + AMDXDNA_BO_DEV_HEAP = 2,
>> + AMDXDNA_BO_DEV = 3,
>> + AMDXDNA_BO_CMD = 4,
>> };
>> /**
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Claude review: accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval
2026-03-20 21:06 [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval Lizhi Hou
2026-03-20 21:46 ` Mario Limonciello (AMD) (kernel.org)
@ 2026-03-21 17:20 ` Claude Code Review Bot
2026-03-21 17:20 ` Claude Code Review Bot
2 siblings, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-03-21 17:20 UTC (permalink / raw)
To: dri-devel-reviews
Overall Series Review
Subject: accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval
Author: Lizhi Hou <lizhi.hou@amd.com>
Patches: 3
Reviewed: 2026-03-22T03:20:50.763382
---
This is a single-patch refactor of the amdxdna GEM BO handling that introduces address-retrieval helper APIs (`amdxdna_gem_vmap`, `amdxdna_gem_uva`, `amdxdna_gem_dev_addr`) and merges the CMD BO type into SHMEM/SHARE. The goals are reasonable: centralizing address logic, removing the special CMD BO type, and preparing for future changes. However, there are several correctness concerns — particularly around concurrency in `amdxdna_gem_vmap()`, removal of the `.close` callback without preserving IOMMU cleanup symmetry, a lost size validation for CMD BOs, and an inconsistency in the ubuf DMA mapping change. The UAPI change to alias `AMDXDNA_BO_SHMEM = AMDXDNA_BO_SHARE = 1` is a reasonable backward-compat approach but deserves explicit documentation.
For a patch claiming "no functional change intended," this makes several behavioral changes (always DMA-mapping ubufs, removing CMD BO size checks, changing IOMMU map/unmap lifetime). It should either be split or the commit message should accurately describe the functional changes.
---
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
* Claude review: accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval
2026-03-20 21:06 [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval Lizhi Hou
2026-03-20 21:46 ` Mario Limonciello (AMD) (kernel.org)
2026-03-21 17:20 ` Claude review: " Claude Code Review Bot
@ 2026-03-21 17:20 ` Claude Code Review Bot
2 siblings, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-03-21 17:20 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**1. Race condition in `amdxdna_gem_vmap()` (amdxdna_gem.c)**
The double-checked locking pattern has a data race. The first read of `abo->mem.kva` is outside the lock and without any memory barrier:
```c
void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
{
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
int ret;
if (abo->mem.kva)
return abo->mem.kva;
/* The first call to get the kva, taking slow path. */
guard(mutex)(&abo->lock);
if (!abo->mem.kva) {
ret = drm_gem_vmap(to_gobj(abo), &map);
...
else
abo->mem.kva = map.vaddr;
}
return abo->mem.kva;
}
```
In the kernel, a plain load of `abo->mem.kva` from one thread while another thread stores under the lock is a data race per KCSAN. Use `READ_ONCE`/`WRITE_ONCE` or `smp_load_acquire`/`smp_store_release` to make this correct. The inner store should use `smp_store_release(&abo->mem.kva, map.vaddr)` and the outer check should use `smp_load_acquire(&abo->mem.kva)`.
**2. `amdxdna_gem_vmap()` called in inline hot-path accessors (amdxdna_ctx.h)**
`amdxdna_cmd_get_op()`, `amdxdna_cmd_set_state()`, and `amdxdna_cmd_get_state()` are small inline helpers that previously did a direct pointer dereference of `abo->mem.kva`. They now call `amdxdna_gem_vmap()` which takes a mutex on the first call and calls `drm_gem_vmap`. These functions are called in the job submission and completion hot paths. While functional, this is a performance regression hiding behind "no functional change." These BOs should already be vmapped by the time these helpers run. Consider asserting rather than silently handling NULL.
**3. Double call to `amdxdna_gem_vmap()` in sync ioctl (amdxdna_gem.c)**
```c
else if (amdxdna_gem_vmap(abo))
drm_clflush_virt_range(amdxdna_gem_vmap(abo) + args->offset, args->size);
```
This calls `amdxdna_gem_vmap()` twice — once for the condition check, once for the argument. While it will return the cached pointer on the second call, this is wasteful and poor style. Use a local variable.
**4. Removal of `.close` callback and IOMMU unmap asymmetry (amdxdna_gem.c)**
The `.open` callback now does `amdxdna_iommu_map_bo()` but there's no corresponding `.close` callback. The IOMMU unmap is instead done in `amdxdna_gem_obj_free()`:
```c
if (amdxdna_iova_on(xdna))
amdxdna_iommu_unmap_bo(xdna, abo);
```
The old code had a ref-counted `.open`/`.close` pair. With the old DRM gem_open/gem_close semantics, `.open` is called for each `drm_file` that gains a handle. If the same BO is opened by multiple files (via prime import or handle duplication), `.open` will be called multiple times but `amdxdna_iommu_map_bo` will only unmap once in `.free`. This could lead to double-mapping or leaked IOMMU mappings depending on `amdxdna_iommu_map_bo`'s idempotency. The refcount removal needs justification.
**5. Lost CMD BO size validation (amdxdna_gem.c)**
The old code had:
```c
if (args->size < sizeof(struct amdxdna_cmd)) {
XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
return ERR_PTR(-EINVAL);
}
```
And in `amdxdna_gem_get_obj`:
```c
if (abo->mem.size > SZ_32K) {
XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
goto put_obj;
}
```
Both are removed. Userspace can now create an SHMEM BO of any size and use it as a command buffer. The minimum size check prevented out-of-bounds reads in `amdxdna_cmd_get_payload()` and friends. The 32K upper bound prevented excessive kernel vmaps. These are security-relevant validations that should be preserved somewhere.
**6. DEV_HEAP size validation changed semantics (amdxdna_gem.c)**
Old code:
```c
if (args->size > xdna->dev_info->dev_mem_size) {
```
New code:
```c
if (!args->size || !IS_ALIGNED(args->size, xdna->dev_info->dev_mem_size)) {
```
The old code checked that the heap doesn't exceed device memory. The new code requires the size to be an exact multiple of `dev_mem_size`. This is a behavioral change — previously a heap of `dev_mem_size / 2` was valid; now it's not. This seems intentional but contradicts "no functional change."
**7. `amdxdna_gem_vmap()` doesn't handle imported BOs (amdxdna_gem.c)**
The old `amdxdna_gem_obj_vmap()` handled both native and imported BOs:
```c
if (is_import_bo(abo))
ret = dma_buf_vmap_unlocked(abo->dma_buf, &map);
else
ret = drm_gem_vmap(to_gobj(abo), &map);
```
The new `amdxdna_gem_vmap()` only calls `drm_gem_vmap()`. For imported BOs, `drm_gem_vmap` would need the object's `.vmap` callback, which is set from the exporter's `dma_buf_ops`. This path may or may not work — it depends on whether `drm_gem_vmap` correctly delegates to the DMA-BUF layer. If it doesn't, vmapping imported BOs will silently fail. The old code explicitly distinguished the two paths for a reason.
Similarly, `amdxdna_gem_vunmap()` only calls `drm_gem_vunmap()` but the old `amdxdna_gem_obj_vunmap()` called `dma_buf_vunmap_unlocked()` for imported BOs.
**8. ubuf always DMA-mapped now (amdxdna_ubuf.c)**
The patch removes the `AMDXDNA_UBUF_FLAG_MAP_DMA` flag and unconditionally calls `dma_map_sgtable()` in `amdxdna_ubuf_map()`. Previously only CMD BOs had their ubufs DMA-mapped. This is a functional change — non-CMD ubufs that were previously not DMA-mapped will now be mapped. This could have performance or correctness implications depending on how those BOs are used.
**9. `abo->client` set in `.open` callback may be too late (amdxdna_gem.c)**
```c
static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *filp)
{
...
if (!abo->client)
abo->client = filp->driver_priv;
```
For SHARE BOs created through `amdxdna_drm_create_share_bo()`, `abo->client` is never set in the creation path (unlike the old code which did `abo->client = client`). It's deferred to `.open`. But `amdxdna_gem_vmap()` accesses `abo->client->xdna` for error logging — if vmap is called before open (which could happen during creation), this will NULL-deref.
**10. UAPI: `AMDXDNA_BO_SHMEM` and `AMDXDNA_BO_SHARE` aliased (amdxdna_accel.h)**
```c
AMDXDNA_BO_SHMEM = 1, /* Be compatible with legacy application code. */
AMDXDNA_BO_SHARE = 1,
```
Having two enum values with the same underlying value is valid C but unusual in kernel UAPI headers. The comment says "legacy application code" but this driver is quite new. If SHMEM is truly being removed, a deprecation notice or compat note in the UAPI header doc comment would be helpful. Also, the kernel code now uses `AMDXDNA_BO_SHARE` internally but accepts `AMDXDNA_BO_CMD` (value 4) via `fallthrough` in the switch — consider adding a comment in the UAPI explaining that CMD is now treated as SHARE.
**11. `amdxdna_gem_dev_obj_vmap` doesn't lock (amdxdna_gem.c)**
```c
static int amdxdna_gem_dev_obj_vmap(struct drm_gem_object *obj, struct iosys_map *map)
{
struct amdxdna_gem_obj *abo = to_xdna_obj(obj);
void *base = amdxdna_gem_vmap(abo->client->dev_heap);
u64 offset = amdxdna_dev_bo_offset(abo);
...
}
```
This accesses `abo->client->dev_heap` without holding any lock. If the dev_heap could be torn down concurrently (e.g., userspace closes the heap handle while another thread vmaps a DEV BO), this could race. The old code didn't have this path at all since DEV BOs computed their KVA from the heap's KVA at allocation time.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-21 17:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-20 21:06 [PATCH V2] accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval Lizhi Hou
2026-03-20 21:46 ` Mario Limonciello (AMD) (kernel.org)
2026-03-21 5:26 ` Lizhi Hou
2026-03-21 17:20 ` Claude review: " Claude Code Review Bot
2026-03-21 17:20 ` Claude Code Review Bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox