accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval

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.

Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Max Zhen <max.zhen@amd.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260320210615.1973016-1-lizhi.hou@amd.com
This commit is contained in:
Max Zhen
2026-03-20 22:12:49 -07:00
committed by Lizhi Hou
parent fbef867cf6
commit d76856beb4
10 changed files with 266 additions and 278 deletions
+4 -4
View File
@@ -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);
+19 -14
View File
@@ -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_SHARE);
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;
+17 -6
View File
@@ -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_SHARE);
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_SHARE);
if (!job->cmd_bo) {
XDNA_ERR(xdna, "Failed to get cmd bo from %d", cmd_bo_hdl);
ret = -EINVAL;
+12 -3
View File
@@ -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);
}
File diff suppressed because it is too large Load Diff
+17 -15
View File
@@ -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);
+1 -1
View File
@@ -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,
};
+4 -13
View File
@@ -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);
-5
View File
@@ -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_ */
+5 -4
View File
@@ -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,
};
/**