linux/drivers/accel/amdxdna/amdxdna_ctx.h
Lizhi Hou 4fd6ca90fc accel/amdxdna: Refactor hardware context destroy routine
It is required by firmware to wait up to 2 seconds for pending commands
before sending the destroy hardware context command. After 2 seconds
wait, if there are still pending commands, driver needs to cancel them.

So the context destroy steps need to be:
  1. Stop drm scheduler. (drm_sched_entity_destroy)
  2. Wait up to 2 seconds for pending commands.
  3. Destroy hardware context and cancel the rest pending requests.
  4. Wait all jobs associated with the hwctx are freed.
  5. Free job resources.

Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250124173536.148676-1-lizhi.hou@amd.com
2025-02-14 08:36:07 -07:00

165 lines
4.3 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022-2024, Advanced Micro Devices, Inc.
*/
#ifndef _AMDXDNA_CTX_H_
#define _AMDXDNA_CTX_H_
#include <linux/bitfield.h>
#include "amdxdna_gem.h"
struct amdxdna_hwctx_priv;
enum ert_cmd_opcode {
ERT_START_CU = 0,
ERT_CMD_CHAIN = 19,
ERT_START_NPU = 20,
};
enum ert_cmd_state {
ERT_CMD_STATE_INVALID,
ERT_CMD_STATE_NEW,
ERT_CMD_STATE_QUEUED,
ERT_CMD_STATE_RUNNING,
ERT_CMD_STATE_COMPLETED,
ERT_CMD_STATE_ERROR,
ERT_CMD_STATE_ABORT,
ERT_CMD_STATE_SUBMITTED,
ERT_CMD_STATE_TIMEOUT,
ERT_CMD_STATE_NORESPONSE,
};
/*
* Interpretation of the beginning of data payload for ERT_START_NPU in
* amdxdna_cmd. The rest of the payload in amdxdna_cmd is regular kernel args.
*/
struct amdxdna_cmd_start_npu {
u64 buffer; /* instruction buffer address */
u32 buffer_size; /* size of buffer in bytes */
u32 prop_count; /* properties count */
u32 prop_args[]; /* properties and regular kernel arguments */
};
/*
* Interpretation of the beginning of data payload for ERT_CMD_CHAIN in
* amdxdna_cmd. The rest of the payload in amdxdna_cmd is cmd BO handles.
*/
struct amdxdna_cmd_chain {
u32 command_count;
u32 submit_index;
u32 error_index;
u32 reserved[3];
u64 data[] __counted_by(command_count);
};
/* Exec buffer command header format */
#define AMDXDNA_CMD_STATE GENMASK(3, 0)
#define AMDXDNA_CMD_EXTRA_CU_MASK GENMASK(11, 10)
#define AMDXDNA_CMD_COUNT GENMASK(22, 12)
#define AMDXDNA_CMD_OPCODE GENMASK(27, 23)
struct amdxdna_cmd {
u32 header;
u32 data[];
};
struct amdxdna_hwctx {
struct amdxdna_client *client;
struct amdxdna_hwctx_priv *priv;
char *name;
u32 id;
u32 max_opc;
u32 num_tiles;
u32 mem_size;
u32 fw_ctx_id;
u32 col_list_len;
u32 *col_list;
u32 start_col;
u32 num_col;
#define HWCTX_STAT_INIT 0
#define HWCTX_STAT_READY 1
#define HWCTX_STAT_STOP 2
u32 status;
u32 old_status;
struct amdxdna_qos_info qos;
struct amdxdna_hwctx_param_config_cu *cus;
u32 syncobj_hdl;
atomic64_t job_submit_cnt;
atomic64_t job_free_cnt ____cacheline_aligned_in_smp;
};
#define drm_job_to_xdna_job(j) \
container_of(j, struct amdxdna_sched_job, base)
struct amdxdna_sched_job {
struct drm_sched_job base;
struct kref refcnt;
struct amdxdna_hwctx *hwctx;
struct mm_struct *mm;
/* The fence to notice DRM scheduler that job is done by hardware */
struct dma_fence *fence;
/* user can wait on this fence */
struct dma_fence *out_fence;
bool job_done;
u64 seq;
struct amdxdna_gem_obj *cmd_bo;
size_t bo_cnt;
struct drm_gem_object *bos[] __counted_by(bo_cnt);
};
static inline u32
amdxdna_cmd_get_op(struct amdxdna_gem_obj *abo)
{
struct amdxdna_cmd *cmd = abo->mem.kva;
return FIELD_GET(AMDXDNA_CMD_OPCODE, cmd->header);
}
static inline void
amdxdna_cmd_set_state(struct amdxdna_gem_obj *abo, enum ert_cmd_state s)
{
struct amdxdna_cmd *cmd = abo->mem.kva;
cmd->header &= ~AMDXDNA_CMD_STATE;
cmd->header |= FIELD_PREP(AMDXDNA_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;
return FIELD_GET(AMDXDNA_CMD_STATE, cmd->header);
}
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size);
int amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo);
static inline u32 amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx)
{
return GENMASK(hwctx->start_col + hwctx->num_col - 1,
hwctx->start_col);
}
void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job);
void amdxdna_hwctx_remove_all(struct amdxdna_client *client);
void amdxdna_hwctx_suspend(struct amdxdna_client *client);
void amdxdna_hwctx_resume(struct amdxdna_client *client);
int amdxdna_cmd_submit(struct amdxdna_client *client,
u32 cmd_bo_hdls, u32 *arg_bo_hdls, u32 arg_bo_cnt,
u32 hwctx_hdl, u64 *seq);
int amdxdna_cmd_wait(struct amdxdna_client *client, u32 hwctx_hdl,
u64 seq, u32 timeout);
int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdxdna_drm_submit_cmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
#endif /* _AMDXDNA_CTX_H_ */