accel/amdxdna: Get device revision to derive VBNV string

Add support for querying the device revision from firmware.

Use the returned revision to look up the VBNV string during device
initialization, and fall back to the default VBNV when the revision
query is not supported or no mapping is found.

This allows the driver to report the accurate VBNV for devices that
share the same vendor/device ID but differ by hardware revision.

Signed-off-by: Max Zhen <max.zhen@amd.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
[Lizhi: Revise amdxdna_vbnv_init()]
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260416190150.1040067-1-lizhi.hou@amd.com
This commit is contained in:
Max Zhen 2026-04-16 12:01:50 -07:00 committed by Lizhi Hou
parent d09339388b
commit d8c33b9c4b
14 changed files with 136 additions and 7 deletions

View File

@ -87,3 +87,33 @@ int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor)
return found ? 0 : -EOPNOTSUPP;
}
static void amdxdna_update_vbnv(struct amdxdna_dev *xdna,
const struct amdxdna_rev_vbnv *tbl,
u32 rev)
{
int i;
for (i = 0; tbl[i].vbnv; i++) {
if (tbl[i].revision == rev) {
xdna->vbnv = tbl[i].vbnv;
break;
}
}
}
void amdxdna_vbnv_init(struct amdxdna_dev *xdna)
{
const struct amdxdna_dev_info *info = xdna->dev_info;
u32 rev;
xdna->vbnv = info->default_vbnv;
if (!info->ops->get_dev_revision || !info->rev_vbnv_tbl)
return;
if (info->ops->get_dev_revision(xdna, &rev))
return;
amdxdna_update_vbnv(xdna, info->rev_vbnv_tbl, rev);
}

View File

@ -82,11 +82,18 @@ struct psp_config {
u32 notify_val;
};
/* Device revision to VBNV string mapping table entry */
struct amdxdna_rev_vbnv {
u32 revision;
const char *vbnv;
};
/* aie.c */
void aie_dump_mgmt_chann_debug(struct aie_device *aie);
void aie_destroy_chann(struct aie_device *aie, struct mailbox_channel **chann);
int aie_send_mgmt_msg_wait(struct aie_device *aie, struct xdna_mailbox_msg *msg);
int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor);
void amdxdna_vbnv_init(struct amdxdna_dev *xdna);
/* aie_psp.c */
struct psp_device *aiem_psp_create(struct drm_device *ddev, struct psp_config *conf);

View File

@ -1244,3 +1244,28 @@ int aie2_update_prop_time_quota(struct amdxdna_dev_hdl *ndev, u32 us)
}
return ret;
}
int aie2_get_dev_revision(struct amdxdna_dev_hdl *ndev, enum aie2_dev_revision *rev)
{
DECLARE_AIE_MSG(get_dev_revision, MSG_OP_GET_DEV_REVISION);
struct amdxdna_dev *xdna = ndev->aie.xdna;
int ret;
if (!AIE_FEATURE_ON(&ndev->aie, AIE2_GET_DEV_REVISION))
return -EOPNOTSUPP;
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret)
return ret;
*rev = resp.rev;
if (*rev < AIE2_DEV_REVISION_STXA || *rev >= AIE2_DEV_REVISION_UNKN) {
XDNA_ERR(xdna, "Unknown device revision: %d (raw fuse: 0x%x)",
*rev, resp.raw_fuse_data);
return -EINVAL;
}
XDNA_DBG(xdna, "Device revision: %d (raw fuse: 0x%x)", *rev, resp.raw_fuse_data);
return 0;
}

View File

@ -33,6 +33,7 @@ enum aie2_msg_opcode {
MSG_OP_REGISTER_ASYNC_EVENT_MSG = 0x10C,
MSG_OP_UPDATE_PROPERTY = 0x113,
MSG_OP_GET_APP_HEALTH = 0x114,
MSG_OP_GET_DEV_REVISION = 0x117,
MSG_OP_MAX_DRV_OPCODE,
MSG_OP_GET_PROTOCOL_VERSION = 0x301,
MSG_OP_MAX_OPCODE
@ -519,4 +520,26 @@ struct update_property_resp {
enum aie2_msg_status status;
} __packed;
enum aie2_dev_revision {
AIE2_DEV_REVISION_STXA = 1,
AIE2_DEV_REVISION_STXB,
AIE2_DEV_REVISION_KRK1,
AIE2_DEV_REVISION_KRK2,
AIE2_DEV_REVISION_HALO,
AIE2_DEV_REVISION_GPT1,
AIE2_DEV_REVISION_GPT2,
AIE2_DEV_REVISION_GPT3,
AIE2_DEV_REVISION_UNKN,
};
struct get_dev_revision_req {
__u32 place_holder;
} __packed;
struct get_dev_revision_resp {
enum aie2_msg_status status;
enum aie2_dev_revision rev;
__u32 raw_fuse_data;
} __packed;
#endif /* _AIE2_MSG_PRIV_H_ */

View File

@ -608,6 +608,7 @@ static int aie2_init(struct amdxdna_dev *xdna)
release_firmware(fw);
aie2_msg_init(ndev);
amdxdna_vbnv_init(xdna);
amdxdna_pm_init(xdna);
return 0;
@ -1255,6 +1256,21 @@ static int aie2_set_state(struct amdxdna_client *client,
return ret;
}
static int aie2_get_dev_rev(struct amdxdna_dev *xdna, u32 *rev)
{
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
enum aie2_dev_revision aie2_rev;
int ret;
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
ret = aie2_get_dev_revision(ndev, &aie2_rev);
if (!ret)
*rev = (u32)aie2_rev;
return ret;
}
const struct amdxdna_dev_ops aie2_ops = {
.init = aie2_init,
.fini = aie2_fini,
@ -1269,4 +1285,5 @@ const struct amdxdna_dev_ops aie2_ops = {
.cmd_submit = aie2_cmd_submit,
.hmm_invalidate = aie2_hmm_invalidate,
.get_array = aie2_get_array,
.get_dev_revision = aie2_get_dev_rev,
};

View File

@ -223,6 +223,7 @@ enum aie2_fw_feature {
AIE2_TEMPORAL_ONLY,
AIE2_APP_HEALTH,
AIE2_UPDATE_PROPERTY,
AIE2_GET_DEV_REVISION,
AIE2_FEATURE_MAX
};
@ -258,6 +259,7 @@ extern const struct dpm_clk_freq npu4_dpm_clk_table[];
extern const struct rt_config npu1_default_rt_cfg[];
extern const struct rt_config npu4_default_rt_cfg[];
extern const struct amdxdna_fw_feature_tbl npu4_fw_feature_table[];
extern const struct amdxdna_rev_vbnv npu4_rev_vbnv_tbl[];
extern const struct aie2_hw_ops npu4_hw_ops;
/* aie2_pm.c */
@ -286,6 +288,7 @@ int aie2_query_firmware_version(struct amdxdna_dev_hdl *ndev,
struct amdxdna_fw_ver *fw_ver);
int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
struct app_health_report *report);
int aie2_get_dev_revision(struct amdxdna_dev_hdl *ndev, enum aie2_dev_revision *rev);
int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx);
int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx);
int aie2_map_host_buf(struct amdxdna_dev_hdl *ndev, u32 context_id, u64 addr, u64 size);

View File

@ -471,6 +471,7 @@ static int aie4_init(struct amdxdna_dev *xdna)
return ret;
}
amdxdna_vbnv_init(xdna);
XDNA_DBG(xdna, "aie4 init finished");
return 0;
}

View File

@ -65,6 +65,7 @@ struct amdxdna_dev_ops {
int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);
int (*get_array)(struct amdxdna_client *client, struct amdxdna_drm_get_array *args);
int (*get_dev_revision)(struct amdxdna_dev *xdna, u32 *rev);
};
struct amdxdna_fw_feature_tbl {
@ -89,7 +90,8 @@ struct amdxdna_dev_info {
u32 dev_mem_buf_shift;
u64 dev_mem_base;
size_t dev_mem_size;
char *vbnv;
const char *default_vbnv;
const struct amdxdna_rev_vbnv *rev_vbnv_tbl;
const struct amdxdna_dev_priv *dev_priv;
const struct amdxdna_fw_feature_tbl *fw_feature_tbl;
const struct amdxdna_dev_ops *ops;
@ -117,6 +119,8 @@ struct amdxdna_dev {
struct iommu_group *group;
struct iommu_domain *domain;
struct iova_domain iovad;
/* Accurate board name queried from firmware, or default_vbnv as fallback */
const char *vbnv;
};
/*

View File

@ -17,7 +17,10 @@ static ssize_t vbnv_show(struct device *dev, struct device_attribute *attr, char
{
struct amdxdna_dev *xdna = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", xdna->dev_info->vbnv);
if (!xdna->vbnv)
return sprintf(buf, "\n");
return sprintf(buf, "%s\n", xdna->vbnv);
}
static DEVICE_ATTR_RO(vbnv);

View File

@ -137,7 +137,7 @@ const struct amdxdna_dev_info dev_npu1_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
.vbnv = "RyzenAI-npu1",
.default_vbnv = "RyzenAI-npu1",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
.dev_priv = &npu1_dev_priv,
.fw_feature_tbl = npu1_fw_feature_table,

View File

@ -69,7 +69,7 @@ const struct amdxdna_dev_info dev_npu3_pf_info = {
.sram_bar = NPU3_MBOX_BUFFER_BAR,
.psp_bar = NPU3_PSP_BAR_INDEX,
.smu_bar = NPU3_SMU_BAR_INDEX,
.vbnv = "RyzenAI-npu3-pf",
.default_vbnv = "RyzenAI-npu3-pf",
.device_type = AMDXDNA_DEV_TYPE_PF,
.dev_priv = &npu3_dev_priv,
.fw_feature_tbl = npu3_fw_feature_table,

View File

@ -98,6 +98,7 @@ const struct amdxdna_fw_feature_tbl npu4_fw_feature_table[] = {
{ .features = BIT_U64(AIE2_NPU_COMMAND), .major = 6, .min_minor = 15 },
{ .features = BIT_U64(AIE2_UPDATE_PROPERTY), .major = 6, .min_minor = 15 },
{ .features = BIT_U64(AIE2_APP_HEALTH), .major = 6, .min_minor = 18 },
{ .features = BIT_U64(AIE2_GET_DEV_REVISION), .major = 6, .min_minor = 24 },
{ .features = AIE2_ALL_FEATURES, .major = 7 },
{ 0 }
};
@ -142,6 +143,18 @@ const struct aie2_hw_ops npu4_hw_ops = {
.update_counters = npu4_update_counters,
};
const struct amdxdna_rev_vbnv npu4_rev_vbnv_tbl[] = {
{ AIE2_DEV_REVISION_STXA, "NPU Strix" },
{ AIE2_DEV_REVISION_STXB, "NPU Strix" },
{ AIE2_DEV_REVISION_KRK1, "NPU Krackan 1" },
{ AIE2_DEV_REVISION_KRK2, "NPU Krackan 2" },
{ AIE2_DEV_REVISION_HALO, "NPU Strix Halo" },
{ AIE2_DEV_REVISION_GPT1, "NPU Gorgon Point 1" },
{ AIE2_DEV_REVISION_GPT2, "NPU Gorgon Point 2" },
{ AIE2_DEV_REVISION_GPT3, "NPU Gorgon Point 3" },
{ 0 }
};
static const struct amdxdna_dev_priv npu4_dev_priv = {
.fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
@ -185,8 +198,9 @@ const struct amdxdna_dev_info dev_npu4_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
.vbnv = "RyzenAI-npu4",
.default_vbnv = "RyzenAI-npu4",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
.rev_vbnv_tbl = npu4_rev_vbnv_tbl,
.dev_priv = &npu4_dev_priv,
.fw_feature_tbl = npu4_fw_feature_table,
.ops = &aie2_ops, /* NPU4 can share NPU1's callback */

View File

@ -105,8 +105,9 @@ const struct amdxdna_dev_info dev_npu5_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
.vbnv = "RyzenAI-npu5",
.default_vbnv = "RyzenAI-npu5",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
.rev_vbnv_tbl = npu4_rev_vbnv_tbl,
.dev_priv = &npu5_dev_priv,
.fw_feature_tbl = npu4_fw_feature_table,
.ops = &aie2_ops,

View File

@ -106,8 +106,9 @@ const struct amdxdna_dev_info dev_npu6_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
.vbnv = "RyzenAI-npu6",
.default_vbnv = "RyzenAI-npu6",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
.rev_vbnv_tbl = npu4_rev_vbnv_tbl,
.dev_priv = &npu6_dev_priv,
.fw_feature_tbl = npu4_fw_feature_table,
.ops = &aie2_ops,