Skip to content

Commit aac2430

Browse files
houlz0507quic-jhugo
authored andcommitted
accel/amdxdna: Add command execution
Add interfaces for user application to submit command and wait for its completion. Co-developed-by: Min Ma <min.ma@amd.com> Signed-off-by: Min Ma <min.ma@amd.com> Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com> Signed-off-by: Lizhi Hou <lizhi.hou@amd.com> Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com> Link: https://patchwork.freedesktop.org/patch/msgid/20241118172942.2014541-8-lizhi.hou@amd.com
1 parent ac49797 commit aac2430

File tree

19 files changed

+1531
-9
lines changed

19 files changed

+1531
-9
lines changed

drivers/accel/amdxdna/aie2_ctx.c

Lines changed: 604 additions & 3 deletions
Large diffs are not rendered by default.

drivers/accel/amdxdna/aie2_message.c

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
*/
55

66
#include <drm/amdxdna_accel.h>
7+
#include <drm/drm_cache.h>
78
#include <drm/drm_device.h>
89
#include <drm/drm_gem.h>
910
#include <drm/drm_gem_shmem_helper.h>
1011
#include <drm/drm_print.h>
12+
#include <drm/gpu_scheduler.h>
1113
#include <linux/bitfield.h>
1214
#include <linux/errno.h>
1315
#include <linux/pci.h>
@@ -362,3 +364,344 @@ int aie2_config_cu(struct amdxdna_hwctx *hwctx)
362364
msg.opcode, resp.status, ret);
363365
return ret;
364366
}
367+
368+
int aie2_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
369+
int (*notify_cb)(void *, const u32 *, size_t))
370+
{
371+
struct mailbox_channel *chann = hwctx->priv->mbox_chann;
372+
struct amdxdna_dev *xdna = hwctx->client->xdna;
373+
struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
374+
union {
375+
struct execute_buffer_req ebuf;
376+
struct exec_dpu_req dpu;
377+
} req;
378+
struct xdna_mailbox_msg msg;
379+
u32 payload_len;
380+
void *payload;
381+
int cu_idx;
382+
int ret;
383+
u32 op;
384+
385+
if (!chann)
386+
return -ENODEV;
387+
388+
payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len);
389+
if (!payload) {
390+
XDNA_ERR(xdna, "Invalid command, cannot get payload");
391+
return -EINVAL;
392+
}
393+
394+
cu_idx = amdxdna_cmd_get_cu_idx(cmd_abo);
395+
if (cu_idx < 0) {
396+
XDNA_DBG(xdna, "Invalid cu idx");
397+
return -EINVAL;
398+
}
399+
400+
op = amdxdna_cmd_get_op(cmd_abo);
401+
switch (op) {
402+
case ERT_START_CU:
403+
if (unlikely(payload_len > sizeof(req.ebuf.payload)))
404+
XDNA_DBG(xdna, "Invalid ebuf payload len: %d", payload_len);
405+
req.ebuf.cu_idx = cu_idx;
406+
memcpy(req.ebuf.payload, payload, sizeof(req.ebuf.payload));
407+
msg.send_size = sizeof(req.ebuf);
408+
msg.opcode = MSG_OP_EXECUTE_BUFFER_CF;
409+
break;
410+
case ERT_START_NPU: {
411+
struct amdxdna_cmd_start_npu *sn = payload;
412+
413+
if (unlikely(payload_len - sizeof(*sn) > sizeof(req.dpu.payload)))
414+
XDNA_DBG(xdna, "Invalid dpu payload len: %d", payload_len);
415+
req.dpu.inst_buf_addr = sn->buffer;
416+
req.dpu.inst_size = sn->buffer_size;
417+
req.dpu.inst_prop_cnt = sn->prop_count;
418+
req.dpu.cu_idx = cu_idx;
419+
memcpy(req.dpu.payload, sn->prop_args, sizeof(req.dpu.payload));
420+
msg.send_size = sizeof(req.dpu);
421+
msg.opcode = MSG_OP_EXEC_DPU;
422+
break;
423+
}
424+
default:
425+
XDNA_DBG(xdna, "Invalid ERT cmd op code: %d", op);
426+
return -EINVAL;
427+
}
428+
msg.handle = job;
429+
msg.notify_cb = notify_cb;
430+
msg.send_data = (u8 *)&req;
431+
print_hex_dump_debug("cmd: ", DUMP_PREFIX_OFFSET, 16, 4, &req,
432+
0x40, false);
433+
434+
ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
435+
if (ret) {
436+
XDNA_ERR(xdna, "Send message failed");
437+
return ret;
438+
}
439+
440+
return 0;
441+
}
442+
443+
static int
444+
aie2_cmdlist_fill_one_slot_cf(void *cmd_buf, u32 offset,
445+
struct amdxdna_gem_obj *abo, u32 *size)
446+
{
447+
struct cmd_chain_slot_execbuf_cf *buf = cmd_buf + offset;
448+
int cu_idx = amdxdna_cmd_get_cu_idx(abo);
449+
u32 payload_len;
450+
void *payload;
451+
452+
if (cu_idx < 0)
453+
return -EINVAL;
454+
455+
payload = amdxdna_cmd_get_payload(abo, &payload_len);
456+
if (!payload)
457+
return -EINVAL;
458+
459+
if (!slot_cf_has_space(offset, payload_len))
460+
return -ENOSPC;
461+
462+
buf->cu_idx = cu_idx;
463+
buf->arg_cnt = payload_len / sizeof(u32);
464+
memcpy(buf->args, payload, payload_len);
465+
/* Accurate buf size to hint firmware to do necessary copy */
466+
*size = sizeof(*buf) + payload_len;
467+
return 0;
468+
}
469+
470+
static int
471+
aie2_cmdlist_fill_one_slot_dpu(void *cmd_buf, u32 offset,
472+
struct amdxdna_gem_obj *abo, u32 *size)
473+
{
474+
struct cmd_chain_slot_dpu *buf = cmd_buf + offset;
475+
int cu_idx = amdxdna_cmd_get_cu_idx(abo);
476+
struct amdxdna_cmd_start_npu *sn;
477+
u32 payload_len;
478+
void *payload;
479+
u32 arg_sz;
480+
481+
if (cu_idx < 0)
482+
return -EINVAL;
483+
484+
payload = amdxdna_cmd_get_payload(abo, &payload_len);
485+
if (!payload)
486+
return -EINVAL;
487+
sn = payload;
488+
arg_sz = payload_len - sizeof(*sn);
489+
if (payload_len < sizeof(*sn) || arg_sz > MAX_DPU_ARGS_SIZE)
490+
return -EINVAL;
491+
492+
if (!slot_dpu_has_space(offset, arg_sz))
493+
return -ENOSPC;
494+
495+
buf->inst_buf_addr = sn->buffer;
496+
buf->inst_size = sn->buffer_size;
497+
buf->inst_prop_cnt = sn->prop_count;
498+
buf->cu_idx = cu_idx;
499+
buf->arg_cnt = arg_sz / sizeof(u32);
500+
memcpy(buf->args, sn->prop_args, arg_sz);
501+
502+
/* Accurate buf size to hint firmware to do necessary copy */
503+
*size += sizeof(*buf) + arg_sz;
504+
return 0;
505+
}
506+
507+
static int
508+
aie2_cmdlist_fill_one_slot(u32 op, struct amdxdna_gem_obj *cmdbuf_abo, u32 offset,
509+
struct amdxdna_gem_obj *abo, u32 *size)
510+
{
511+
u32 this_op = amdxdna_cmd_get_op(abo);
512+
void *cmd_buf = cmdbuf_abo->mem.kva;
513+
int ret;
514+
515+
if (this_op != op) {
516+
ret = -EINVAL;
517+
goto done;
518+
}
519+
520+
switch (op) {
521+
case ERT_START_CU:
522+
ret = aie2_cmdlist_fill_one_slot_cf(cmd_buf, offset, abo, size);
523+
break;
524+
case ERT_START_NPU:
525+
ret = aie2_cmdlist_fill_one_slot_dpu(cmd_buf, offset, abo, size);
526+
break;
527+
default:
528+
ret = -EOPNOTSUPP;
529+
}
530+
531+
done:
532+
if (ret) {
533+
XDNA_ERR(abo->client->xdna, "Can't fill slot for cmd op %d ret %d",
534+
op, ret);
535+
}
536+
return ret;
537+
}
538+
539+
static inline struct amdxdna_gem_obj *
540+
aie2_cmdlist_get_cmd_buf(struct amdxdna_sched_job *job)
541+
{
542+
int idx = get_job_idx(job->seq);
543+
544+
return job->hwctx->priv->cmd_buf[idx];
545+
}
546+
547+
static void
548+
aie2_cmdlist_prepare_request(struct cmd_chain_req *req,
549+
struct amdxdna_gem_obj *cmdbuf_abo, u32 size, u32 cnt)
550+
{
551+
req->buf_addr = cmdbuf_abo->mem.dev_addr;
552+
req->buf_size = size;
553+
req->count = cnt;
554+
drm_clflush_virt_range(cmdbuf_abo->mem.kva, size);
555+
XDNA_DBG(cmdbuf_abo->client->xdna, "Command buf addr 0x%llx size 0x%x count %d",
556+
req->buf_addr, size, cnt);
557+
}
558+
559+
static inline u32
560+
aie2_cmd_op_to_msg_op(u32 op)
561+
{
562+
switch (op) {
563+
case ERT_START_CU:
564+
return MSG_OP_CHAIN_EXEC_BUFFER_CF;
565+
case ERT_START_NPU:
566+
return MSG_OP_CHAIN_EXEC_DPU;
567+
default:
568+
return MSG_OP_MAX_OPCODE;
569+
}
570+
}
571+
572+
int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
573+
struct amdxdna_sched_job *job,
574+
int (*notify_cb)(void *, const u32 *, size_t))
575+
{
576+
struct amdxdna_gem_obj *cmdbuf_abo = aie2_cmdlist_get_cmd_buf(job);
577+
struct mailbox_channel *chann = hwctx->priv->mbox_chann;
578+
struct amdxdna_client *client = hwctx->client;
579+
struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
580+
struct amdxdna_cmd_chain *payload;
581+
struct xdna_mailbox_msg msg;
582+
struct cmd_chain_req req;
583+
u32 payload_len;
584+
u32 offset = 0;
585+
u32 size;
586+
int ret;
587+
u32 op;
588+
u32 i;
589+
590+
op = amdxdna_cmd_get_op(cmd_abo);
591+
payload = amdxdna_cmd_get_payload(cmd_abo, &payload_len);
592+
if (op != ERT_CMD_CHAIN || !payload ||
593+
payload_len < struct_size(payload, data, payload->command_count))
594+
return -EINVAL;
595+
596+
for (i = 0; i < payload->command_count; i++) {
597+
u32 boh = (u32)(payload->data[i]);
598+
struct amdxdna_gem_obj *abo;
599+
600+
abo = amdxdna_gem_get_obj(client, boh, AMDXDNA_BO_CMD);
601+
if (!abo) {
602+
XDNA_ERR(client->xdna, "Failed to find cmd BO %d", boh);
603+
return -ENOENT;
604+
}
605+
606+
/* All sub-cmd should have same op, use the first one. */
607+
if (i == 0)
608+
op = amdxdna_cmd_get_op(abo);
609+
610+
ret = aie2_cmdlist_fill_one_slot(op, cmdbuf_abo, offset, abo, &size);
611+
amdxdna_gem_put_obj(abo);
612+
if (ret)
613+
return -EINVAL;
614+
615+
offset += size;
616+
}
617+
618+
/* The offset is the accumulated total size of the cmd buffer */
619+
aie2_cmdlist_prepare_request(&req, cmdbuf_abo, offset, payload->command_count);
620+
621+
msg.opcode = aie2_cmd_op_to_msg_op(op);
622+
if (msg.opcode == MSG_OP_MAX_OPCODE)
623+
return -EOPNOTSUPP;
624+
msg.handle = job;
625+
msg.notify_cb = notify_cb;
626+
msg.send_data = (u8 *)&req;
627+
msg.send_size = sizeof(req);
628+
ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
629+
if (ret) {
630+
XDNA_ERR(hwctx->client->xdna, "Send message failed");
631+
return ret;
632+
}
633+
634+
return 0;
635+
}
636+
637+
int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx,
638+
struct amdxdna_sched_job *job,
639+
int (*notify_cb)(void *, const u32 *, size_t))
640+
{
641+
struct amdxdna_gem_obj *cmdbuf_abo = aie2_cmdlist_get_cmd_buf(job);
642+
struct mailbox_channel *chann = hwctx->priv->mbox_chann;
643+
struct amdxdna_gem_obj *cmd_abo = job->cmd_bo;
644+
struct xdna_mailbox_msg msg;
645+
struct cmd_chain_req req;
646+
u32 size;
647+
int ret;
648+
u32 op;
649+
650+
op = amdxdna_cmd_get_op(cmd_abo);
651+
ret = aie2_cmdlist_fill_one_slot(op, cmdbuf_abo, 0, cmd_abo, &size);
652+
if (ret)
653+
return ret;
654+
655+
aie2_cmdlist_prepare_request(&req, cmdbuf_abo, size, 1);
656+
657+
msg.opcode = aie2_cmd_op_to_msg_op(op);
658+
if (msg.opcode == MSG_OP_MAX_OPCODE)
659+
return -EOPNOTSUPP;
660+
msg.handle = job;
661+
msg.notify_cb = notify_cb;
662+
msg.send_data = (u8 *)&req;
663+
msg.send_size = sizeof(req);
664+
ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
665+
if (ret) {
666+
XDNA_ERR(hwctx->client->xdna, "Send message failed");
667+
return ret;
668+
}
669+
670+
return 0;
671+
}
672+
673+
int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
674+
int (*notify_cb)(void *, const u32 *, size_t))
675+
{
676+
struct mailbox_channel *chann = hwctx->priv->mbox_chann;
677+
struct amdxdna_gem_obj *abo = to_xdna_obj(job->bos[0]);
678+
struct amdxdna_dev *xdna = hwctx->client->xdna;
679+
struct xdna_mailbox_msg msg;
680+
struct sync_bo_req req;
681+
int ret = 0;
682+
683+
req.src_addr = 0;
684+
req.dst_addr = abo->mem.dev_addr - hwctx->client->dev_heap->mem.dev_addr;
685+
req.size = abo->mem.size;
686+
687+
/* Device to Host */
688+
req.type = FIELD_PREP(AIE2_MSG_SYNC_BO_SRC_TYPE, SYNC_BO_DEV_MEM) |
689+
FIELD_PREP(AIE2_MSG_SYNC_BO_DST_TYPE, SYNC_BO_HOST_MEM);
690+
691+
XDNA_DBG(xdna, "sync %d bytes src(0x%llx) to dst(0x%llx) completed",
692+
req.size, req.src_addr, req.dst_addr);
693+
694+
msg.handle = job;
695+
msg.notify_cb = notify_cb;
696+
msg.send_data = (u8 *)&req;
697+
msg.send_size = sizeof(req);
698+
msg.opcode = MSG_OP_SYNC_BO;
699+
700+
ret = xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT);
701+
if (ret) {
702+
XDNA_ERR(xdna, "Send message failed");
703+
return ret;
704+
}
705+
706+
return 0;
707+
}

drivers/accel/amdxdna/aie2_pci.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
#include <drm/amdxdna_accel.h>
77
#include <drm/drm_device.h>
8+
#include <drm/drm_gem_shmem_helper.h>
89
#include <drm/drm_managed.h>
910
#include <drm/drm_print.h>
11+
#include <drm/gpu_scheduler.h>
1012
#include <linux/errno.h>
1113
#include <linux/firmware.h>
1214
#include <linux/iommu.h>
@@ -17,6 +19,7 @@
1719
#include "aie2_pci.h"
1820
#include "aie2_solver.h"
1921
#include "amdxdna_ctx.h"
22+
#include "amdxdna_gem.h"
2023
#include "amdxdna_mailbox.h"
2124
#include "amdxdna_pci_drv.h"
2225

@@ -496,4 +499,6 @@ const struct amdxdna_dev_ops aie2_ops = {
496499
.hwctx_init = aie2_hwctx_init,
497500
.hwctx_fini = aie2_hwctx_fini,
498501
.hwctx_config = aie2_hwctx_config,
502+
.cmd_submit = aie2_cmd_submit,
503+
.hmm_invalidate = aie2_hmm_invalidate,
499504
};

0 commit comments

Comments
 (0)