staticint aie2_max_col = XRS_MAX_COL;
module_param(aie2_max_col, uint, 0600);
MODULE_PARM_DESC(aie2_max_col, "Maximum column could be used");
/* * The management mailbox channel is allocated by firmware. * The related register and ring buffer information is on SRAM BAR. * This struct is the register layout.
*/ #define MGMT_MBOX_MAGIC 0x55504e5f /* _NPU */ struct mgmt_mbox_chann_info {
__u32 x2i_tail;
__u32 x2i_head;
__u32 x2i_buf;
__u32 x2i_buf_sz;
__u32 i2x_tail;
__u32 i2x_head;
__u32 i2x_buf;
__u32 i2x_buf_sz;
__u32 magic;
__u32 msi_id;
__u32 prot_major;
__u32 prot_minor;
__u32 rsvd[4];
};
/* * The driver supported mailbox behavior is defined by * ndev->priv->protocol_major and protocol_minor. * * When protocol_major and fw_major are different, it means driver * and firmware are incompatible.
*/ if (ndev->priv->protocol_major != fw_major) {
XDNA_ERR(xdna, "Incompatible firmware protocol major %d minor %d",
fw_major, fw_minor); return -EINVAL;
}
/* * When protocol_minor is greater then fw_minor, that means driver * relies on operation the installed firmware does not support.
*/ if (ndev->priv->protocol_minor > fw_minor) {
XDNA_ERR(xdna, "Firmware minor version smaller than supported"); return -EINVAL;
} return 0;
}
/* * Once firmware is alive, it will write management channel * information in SRAM BAR and write the address of that information * at FW_ALIVE_OFF offset in SRMA BAR. * * Read a non-zero value from FW_ALIVE_OFF implies that firmware * is alive.
*/
ret = readx_poll_timeout(readl, SRAM_GET_ADDR(ndev, FW_ALIVE_OFF),
addr, addr, AIE2_INTERVAL, AIE2_TIMEOUT); if (ret || !addr) return -ETIME;
off = AIE2_SRAM_OFF(ndev, addr);
reg = (u32 *)&info_regs; for (i = 0; i < sizeof(info_regs) / sizeof(u32); i++)
reg[i] = readl(ndev->sram_base + off + i * sizeof(u32));
if (info_regs.magic != MGMT_MBOX_MAGIC) {
XDNA_ERR(ndev->xdna, "Invalid mbox magic 0x%x", info_regs.magic);
ret = -EINVAL; goto done;
}
ret = aie2_check_protocol(ndev, ndev->mgmt_prot_major, ndev->mgmt_prot_minor);
done:
aie2_dump_chann_info_debug(ndev);
/* Must clear address at FW_ALIVE_OFF */
writel(0, SRAM_GET_ADDR(ndev, FW_ALIVE_OFF));
return ret;
}
int aie2_runtime_cfg(struct amdxdna_dev_hdl *ndev, enum rt_config_category category, u32 *val)
{ conststruct rt_config *cfg;
u32 value; int ret;
for (cfg = ndev->priv->rt_config; cfg->type; cfg++) { if (cfg->category != category) continue;
value = val ? *val : cfg->value;
ret = aie2_set_runtime_cfg(ndev, cfg->type, value); if (ret) {
XDNA_ERR(ndev->xdna, "Set type %d value %d failed",
cfg->type, value); return ret;
}
}
return 0;
}
staticint aie2_xdna_reset(struct amdxdna_dev_hdl *ndev)
{ int ret;
ret = aie2_suspend_fw(ndev); if (ret) {
XDNA_ERR(ndev->xdna, "Suspend firmware failed"); return ret;
}
ret = aie2_resume_fw(ndev); if (ret) {
XDNA_ERR(ndev->xdna, "Resume firmware failed"); return ret;
}
return 0;
}
staticint aie2_mgmt_fw_init(struct amdxdna_dev_hdl *ndev)
{ int ret;
ret = aie2_runtime_cfg(ndev, AIE2_RT_CFG_INIT, NULL); if (ret) {
XDNA_ERR(ndev->xdna, "Runtime config failed"); return ret;
}
ret = aie2_assign_mgmt_pasid(ndev, 0); if (ret) {
XDNA_ERR(ndev->xdna, "Can not assign PASID"); return ret;
}
ret = aie2_xdna_reset(ndev); if (ret) {
XDNA_ERR(ndev->xdna, "Reset firmware failed"); return ret;
}
if (!ndev->async_events) return 0;
ret = aie2_error_async_events_send(ndev); if (ret) {
XDNA_ERR(ndev->xdna, "Send async events failed"); return ret;
}
return 0;
}
staticint aie2_mgmt_fw_query(struct amdxdna_dev_hdl *ndev)
{ int ret;
ret = aie2_query_firmware_version(ndev, &ndev->xdna->fw_ver); if (ret) {
XDNA_ERR(ndev->xdna, "query firmware version failed"); return ret;
}
ret = aie2_query_aie_version(ndev, &ndev->version); if (ret) {
XDNA_ERR(ndev->xdna, "Query AIE version failed"); return ret;
}
ret = aie2_query_aie_metadata(ndev, &ndev->metadata); if (ret) {
XDNA_ERR(ndev->xdna, "Query AIE metadata failed"); return ret;
}
ret = request_firmware(&fw, ndev->priv->fw_path, &pdev->dev); if (ret) {
XDNA_ERR(xdna, "failed to request_firmware %s, ret %d",
ndev->priv->fw_path, ret); return ret;
}
ret = pcim_enable_device(pdev); if (ret) {
XDNA_ERR(xdna, "pcim enable device failed, ret %d", ret); goto release_fw;
}
for (i = 0; i < PSP_MAX_REGS; i++)
set_bit(PSP_REG_BAR(ndev, i), &bars);
for (i = 0; i < PCI_NUM_RESOURCES; i++) { if (!test_bit(i, &bars)) continue;
tbl[i] = pcim_iomap(pdev, i, 0); if (!tbl[i]) {
XDNA_ERR(xdna, "map bar %d failed", i);
ret = -ENOMEM; goto release_fw;
}
}
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (ret) {
XDNA_ERR(xdna, "Failed to set DMA mask: %d", ret); goto release_fw;
}
nvec = pci_msix_vec_count(pdev); if (nvec <= 0) {
XDNA_ERR(xdna, "does not get number of interrupt vector");
ret = -EINVAL; goto release_fw;
}
ret = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSIX); if (ret < 0) {
XDNA_ERR(xdna, "failed to alloc irq vectors, ret %d", ret); goto release_fw;
}
psp_conf.fw_size = fw->size;
psp_conf.fw_buf = fw->data; for (i = 0; i < PSP_MAX_REGS; i++)
psp_conf.psp_regs[i] = tbl[PSP_REG_BAR(ndev, i)] + PSP_REG_OFF(ndev, i);
ndev->psp_hdl = aie2m_psp_create(&xdna->ddev, &psp_conf); if (!ndev->psp_hdl) {
XDNA_ERR(xdna, "failed to create psp");
ret = -ENOMEM; goto free_irq;
}
xdna->dev_handle = ndev;
ret = aie2_hw_start(xdna); if (ret) {
XDNA_ERR(xdna, "start npu failed, ret %d", ret); goto free_irq;
}
ret = aie2_mgmt_fw_query(ndev); if (ret) {
XDNA_ERR(xdna, "Query firmware failed, ret %d", ret); goto stop_hw;
}
ndev->total_col = min(aie2_max_col, ndev->metadata.cols);
xrs_cfg.clk_list.num_levels = ndev->max_dpm_level + 1; for (i = 0; i < xrs_cfg.clk_list.num_levels; i++)
xrs_cfg.clk_list.cu_clk_list[i] = ndev->priv->dpm_clk_tbl[i].hclk;
xrs_cfg.sys_eff_factor = 1;
xrs_cfg.ddev = &xdna->ddev;
xrs_cfg.actions = &aie2_xrs_actions;
xrs_cfg.total_col = ndev->total_col;
xdna->xrs_hdl = xrsm_init(&xrs_cfg); if (!xdna->xrs_hdl) {
XDNA_ERR(xdna, "Initialize resolver failed");
ret = -EINVAL; goto stop_hw;
}
ret = aie2_error_async_events_alloc(ndev); if (ret) {
XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret); goto stop_hw;
}
ret = aie2_error_async_events_send(ndev); if (ret) {
XDNA_ERR(xdna, "Send async events failed, ret %d", ret); goto async_event_free;
}
/* Issue a command to make sure firmware handled async events */
ret = aie2_query_firmware_version(ndev, &ndev->xdna->fw_ver); if (ret) {
XDNA_ERR(xdna, "Re-query firmware version failed"); goto async_event_free;
}
ndev = xdna->dev_handle; if (copy_from_user(&status, u64_to_user_ptr(args->buffer), sizeof(status))) {
XDNA_ERR(xdna, "Failed to copy AIE request into kernel"); return -EFAULT;
}
if (ndev->metadata.cols * ndev->metadata.size < status.buffer_size) {
XDNA_ERR(xdna, "Invalid buffer size. Given Size: %u. Need Size: %u.",
status.buffer_size, ndev->metadata.cols * ndev->metadata.size); return -EINVAL;
}
ret = aie2_query_status(ndev, u64_to_user_ptr(status.buffer),
status.buffer_size, &status.cols_filled); if (ret) {
XDNA_ERR(xdna, "Failed to get AIE status info. Ret: %d", ret); return ret;
}
if (copy_to_user(u64_to_user_ptr(args->buffer), &status, sizeof(status))) {
XDNA_ERR(xdna, "Failed to copy AIE request info to user space"); return -EFAULT;
}
if (!drm_dev_enter(&xdna->ddev, &idx)) return -ENODEV;
switch (args->param) { case DRM_AMDXDNA_QUERY_AIE_STATUS:
ret = aie2_get_aie_status(client, args); break; case DRM_AMDXDNA_QUERY_AIE_METADATA:
ret = aie2_get_aie_metadata(client, args); break; case DRM_AMDXDNA_QUERY_AIE_VERSION:
ret = aie2_get_aie_version(client, args); break; case DRM_AMDXDNA_QUERY_CLOCK_METADATA:
ret = aie2_get_clock_metadata(client, args); break; case DRM_AMDXDNA_QUERY_HW_CONTEXTS:
ret = aie2_get_hwctx_status(client, args); break; case DRM_AMDXDNA_QUERY_FIRMWARE_VERSION:
ret = aie2_get_firmware_version(client, args); break; case DRM_AMDXDNA_GET_POWER_MODE:
ret = aie2_get_power_mode(client, args); break; default:
XDNA_ERR(xdna, "Not supported request parameter %u", args->param);
ret = -EOPNOTSUPP;
}
XDNA_DBG(xdna, "Got param %d", args->param);
if (copy_from_user(&power_state, u64_to_user_ptr(args->buffer), sizeof(power_state))) {
XDNA_ERR(xdna, "Failed to copy power mode request into kernel"); return -EFAULT;
}
if (XDNA_MBZ_DBG(xdna, power_state.pad, sizeof(power_state.pad))) return -EINVAL;
power_mode = power_state.power_mode; if (power_mode > POWER_MODE_TURBO) {
XDNA_ERR(xdna, "Invalid power mode %d", power_mode); return -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.