mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+187
-213
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user