From: Yidong Zhang <yidong.zhang@amd.com>
To: <arnd@arndb.de>, <gregkh@linuxfoundation.org>,
<linux-kernel@vger.kernel.org>
Cc: Yidong Zhang <yidong.zhang@amd.com>, <lizhi.hou@amd.com>,
<christophe.jaillet@wanadoo.fr>, Nishad Saraf <nishads@amd.com>
Subject: [PATCH V0 3/3] drivers/misc/amd: Add load base shell firmware
Date: Sun, 2 Mar 2025 20:43:12 -0800 [thread overview]
Message-ID: <20250303044313.679012-4-yidong.zhang@amd.com> (raw)
In-Reply-To: <20250303044313.679012-1-yidong.zhang@amd.com>
- programming FW
- The base FW is downloaded onto the flash of the card.
- The APU FW is downloaded once after a POR (power on reset).
- Reloading the driver will not change any existing hardware.
Co-developed-by: Nishad Saraf <nishads@amd.com>
Signed-off-by: Nishad Saraf <nishads@amd.com>
Signed-off-by: Yidong Zhang <yidong.zhang@amd.com>
---
drivers/misc/amd/Makefile | 3 +-
drivers/misc/amd/versal-pci-main.c | 45 +-
drivers/misc/amd/versal-pci-rm-queue.c | 14 +-
drivers/misc/amd/versal-pci-rm-service.c | 497 +++++++++++++++++++++++
drivers/misc/amd/versal-pci-rm-service.h | 20 +
drivers/misc/amd/versal-pci.h | 1 +
6 files changed, 569 insertions(+), 11 deletions(-)
create mode 100644 drivers/misc/amd/versal-pci-rm-service.c
diff --git a/drivers/misc/amd/Makefile b/drivers/misc/amd/Makefile
index 63879800a3e5..03394b06fd33 100644
--- a/drivers/misc/amd/Makefile
+++ b/drivers/misc/amd/Makefile
@@ -3,4 +3,5 @@
obj-$(CONFIG_AMD_VERSAL_PCI) += versal-pci.o
versal-pci-$(CONFIG_AMD_VERSAL_PCI) := versal-pci-main.o \
- versal-pci-rm-queue.o
+ versal-pci-rm-queue.o \
+ versal-pci-rm-service.o
diff --git a/drivers/misc/amd/versal-pci-main.c b/drivers/misc/amd/versal-pci-main.c
index 1c61c88120b4..6d3a2833f0c4 100644
--- a/drivers/misc/amd/versal-pci-main.c
+++ b/drivers/misc/amd/versal-pci-main.c
@@ -8,6 +8,8 @@
#include <linux/pci.h>
#include "versal-pci.h"
+#include "versal-pci-rm-service.h"
+#include "versal-pci-rm-queue.h"
#define DRV_NAME "amd-versal-pci"
@@ -21,6 +23,29 @@ static inline u32 versal_pci_devid(struct versal_pci_device *vdev)
PCI_DEVID(vdev->pdev->bus->number, vdev->pdev->devfn));
}
+static int versal_pci_upload_fw(struct versal_pci_device *vdev,
+ enum rm_queue_opcode opcode,
+ const char *data,
+ size_t size)
+{
+ struct rm_cmd *cmd;
+ int ret;
+
+ ret = rm_queue_create_cmd(vdev->rdev, opcode, &cmd);
+ if (ret)
+ return ret;
+
+ ret = rm_queue_data_init(cmd, data, size);
+ if (ret)
+ goto done;
+
+ ret = rm_queue_send_cmd(cmd, RM_CMD_WAIT_DOWNLOAD_TIMEOUT);
+
+done:
+ rm_queue_destroy_cmd(cmd);
+ return ret;
+}
+
static int versal_pci_load_shell(struct versal_pci_device *vdev, char *fw_name)
{
const struct firmware *fw;
@@ -57,7 +82,8 @@ static int versal_pci_load_shell(struct versal_pci_device *vdev, char *fw_name)
goto release_firmware;
}
- /* TODO upload fw to card */
+ ret = versal_pci_upload_fw(vdev, RM_QUEUE_OP_LOAD_FW,
+ (char *)xsabin, xsabin->header.length);
if (ret) {
vdev_err(vdev, "failed to load xsabin %s : %d", fw_name, ret);
goto release_firmware;
@@ -159,6 +185,7 @@ static void versal_pci_device_teardown(struct versal_pci_device *vdev)
{
versal_pci_cfs_fini(&vdev->cfs_subsys);
versal_pci_fw_fini(vdev);
+ versal_pci_rm_fini(vdev->rdev);
}
static void versal_pci_uuid_parse(struct versal_pci_device *vdev, uuid_t *uuid)
@@ -180,7 +207,13 @@ static void versal_pci_uuid_parse(struct versal_pci_device *vdev, uuid_t *uuid)
static int versal_pci_fw_init(struct versal_pci_device *vdev)
{
- /* TODO request compatible fw_id from card */
+ int ret;
+
+ ret = rm_queue_get_fw_id(vdev->rdev);
+ if (ret) {
+ vdev_warn(vdev, "Failed to get fw_id");
+ return -EINVAL;
+ }
versal_pci_uuid_parse(vdev, &vdev->intf_uuid);
@@ -191,6 +224,13 @@ static int versal_pci_device_setup(struct versal_pci_device *vdev)
{
int ret;
+ vdev->rdev = versal_pci_rm_init(vdev);
+ if (IS_ERR(vdev->rdev)) {
+ ret = PTR_ERR(vdev->rdev);
+ vdev_err(vdev, "Failed to init remote queue, err %d", ret);
+ return ret;
+ }
+
ret = versal_pci_fw_init(vdev);
if (ret) {
vdev_err(vdev, "Failed to init fw, err %d", ret);
@@ -206,6 +246,7 @@ static int versal_pci_device_setup(struct versal_pci_device *vdev)
return 0;
comm_chan_fini:
+ versal_pci_rm_fini(vdev->rdev);
return ret;
}
diff --git a/drivers/misc/amd/versal-pci-rm-queue.c b/drivers/misc/amd/versal-pci-rm-queue.c
index 8c1aca442253..7afc5a1e238c 100644
--- a/drivers/misc/amd/versal-pci-rm-queue.c
+++ b/drivers/misc/amd/versal-pci-rm-queue.c
@@ -23,37 +23,35 @@ static inline struct rm_device *to_rdev_msg_timer(struct timer_list *t)
static inline u32 rm_io_read(struct rm_device *rdev, u32 offset)
{
- /* TODO */
- return 0;
+ return rm_reg_read(rdev, RM_PCI_IO_BAR_OFF + offset);
}
static inline int rm_io_write(struct rm_device *rdev, u32 offset, u32 value)
{
- /* TODO */
+ rm_reg_write(rdev, RM_PCI_IO_BAR_OFF + offset, value);
return 0;
}
static inline u32 rm_queue_read(struct rm_device *rdev, u32 offset)
{
- /* TODO */
- return 0;
+ return rm_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset);
}
static inline void rm_queue_write(struct rm_device *rdev, u32 offset, u32 value)
{
- /* TODO */
+ rm_reg_write(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset, value);
}
static inline void rm_queue_bulk_read(struct rm_device *rdev, u32 offset,
u32 *value, u32 size)
{
- /* TODO */
+ rm_bulk_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset, value, size);
}
static inline void rm_queue_bulk_write(struct rm_device *rdev, u32 offset,
u32 *value, u32 size)
{
- /* TODO */
+ rm_bulk_reg_write(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset, value, size);
}
static inline u32 rm_queue_get_cidx(struct rm_device *rdev, enum rm_queue_type type)
diff --git a/drivers/misc/amd/versal-pci-rm-service.c b/drivers/misc/amd/versal-pci-rm-service.c
new file mode 100644
index 000000000000..6dbad1c6563d
--- /dev/null
+++ b/drivers/misc/amd/versal-pci-rm-service.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Versal PCIe device
+ *
+ * Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include "versal-pci.h"
+#include "versal-pci-rm-service.h"
+#include "versal-pci-rm-queue.h"
+
+static DEFINE_IDA(rm_cmd_ids);
+
+static void rm_uninstall_health_monitor(struct rm_device *rdev);
+
+static inline struct rm_device *to_rdev_health_monitor(struct work_struct *w)
+{
+ return container_of(w, struct rm_device, health_monitor);
+}
+
+static inline struct rm_device *to_rdev_health_timer(struct timer_list *t)
+{
+ return container_of(t, struct rm_device, health_timer);
+}
+
+u32 rm_reg_read(struct rm_device *rdev, u32 offset)
+{
+ return readl(rdev->vdev->io_regs + offset);
+}
+
+void rm_reg_write(struct rm_device *rdev, u32 offset, const u32 value)
+{
+ writel(value, rdev->vdev->io_regs + offset);
+}
+
+void rm_bulk_reg_read(struct rm_device *rdev, u32 offset, u32 *value, size_t size)
+{
+ void __iomem *src = rdev->vdev->io_regs + offset;
+ void *dst = (void *)value;
+
+ memcpy_fromio(dst, src, size);
+ /* Barrier of reading data from device */
+ rmb();
+}
+
+void rm_bulk_reg_write(struct rm_device *rdev, u32 offset, const void *value, size_t size)
+{
+ void __iomem *dst = rdev->vdev->io_regs + offset;
+
+ memcpy_toio(dst, value, size);
+ /* Barrier of writing data to device */
+ wmb();
+}
+
+static inline u32 rm_shmem_read(struct rm_device *rdev, u32 offset)
+{
+ return rm_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + offset);
+}
+
+static inline void rm_shmem_bulk_read(struct rm_device *rdev, u32 offset,
+ u32 *value, u32 size)
+{
+ rm_bulk_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + offset, value, size);
+}
+
+static inline void rm_shmem_bulk_write(struct rm_device *rdev, u32 offset,
+ const void *value, u32 size)
+{
+ rm_bulk_reg_write(rdev, RM_PCI_SHMEM_BAR_OFF + offset, value, size);
+}
+
+void rm_queue_destroy_cmd(struct rm_cmd *cmd)
+{
+ ida_free(&rm_cmd_ids, cmd->sq_msg.hdr.id);
+ kfree(cmd);
+}
+
+static int rm_queue_copy_response(struct rm_cmd *cmd, void *buffer, ssize_t len)
+{
+ struct rm_cmd_cq_log_page *result = &cmd->cq_msg.data.page;
+ u64 off = cmd->sq_msg.data.page.address;
+
+ if (!result->len || len < result->len) {
+ vdev_err(cmd->rdev->vdev, "Invalid response or buffer size");
+ return -EINVAL;
+ }
+
+ rm_shmem_bulk_read(cmd->rdev, off, (u32 *)buffer, result->len);
+ return 0;
+}
+
+static void rm_queue_payload_fini(struct rm_cmd *cmd)
+{
+ up(&cmd->rdev->cq.data_lock);
+}
+
+static int rm_queue_payload_init(struct rm_cmd *cmd,
+ enum rm_cmd_log_page_type type)
+{
+ struct rm_device *rdev = cmd->rdev;
+ int ret;
+
+ ret = down_interruptible(&rdev->cq.data_lock);
+ if (ret)
+ return ret;
+
+ cmd->sq_msg.data.page.address = rdev->cq.data_offset;
+ cmd->sq_msg.data.page.size = rdev->cq.data_size;
+ cmd->sq_msg.data.page.reserved1 = 0;
+ cmd->sq_msg.data.page.type = FIELD_PREP(RM_CMD_LOG_PAGE_TYPE_MASK,
+ type);
+ return 0;
+}
+
+void rm_queue_data_fini(struct rm_cmd *cmd)
+{
+ up(&cmd->rdev->sq.data_lock);
+}
+
+int rm_queue_data_init(struct rm_cmd *cmd, const char *buffer, ssize_t size)
+{
+ struct rm_device *rdev = cmd->rdev;
+ int ret;
+
+ if (!size || size > rdev->sq.data_size) {
+ vdev_err(rdev->vdev, "Unsupported file size");
+ return -ENOMEM;
+ }
+
+ ret = down_interruptible(&rdev->sq.data_lock);
+ if (ret)
+ return ret;
+
+ rm_shmem_bulk_write(cmd->rdev, rdev->sq.data_offset, buffer, size);
+
+ cmd->sq_msg.data.bin.address = rdev->sq.data_offset;
+ cmd->sq_msg.data.bin.size = size;
+ return 0;
+}
+
+int rm_queue_create_cmd(struct rm_device *rdev, enum rm_queue_opcode opcode,
+ struct rm_cmd **cmd_ptr)
+{
+ struct rm_cmd *cmd = NULL;
+ int ret, id;
+ u16 size;
+
+ if (rdev->firewall_tripped)
+ return -ENODEV;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+ cmd->rdev = rdev;
+
+ switch (opcode) {
+ case RM_QUEUE_OP_LOAD_XCLBIN:
+ fallthrough;
+ case RM_QUEUE_OP_LOAD_FW:
+ fallthrough;
+ case RM_QUEUE_OP_LOAD_APU_FW:
+ size = sizeof(struct rm_cmd_sq_bin);
+ break;
+ case RM_QUEUE_OP_GET_LOG_PAGE:
+ size = sizeof(struct rm_cmd_sq_log_page);
+ break;
+ case RM_QUEUE_OP_IDENTIFY:
+ size = 0;
+ break;
+ case RM_QUEUE_OP_VMR_CONTROL:
+ size = sizeof(struct rm_cmd_sq_ctrl);
+ break;
+ default:
+ vdev_err(rdev->vdev, "Invalid cmd opcode %d", opcode);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ cmd->opcode = opcode;
+ cmd->sq_msg.hdr.opcode = FIELD_PREP(RM_CMD_SQ_HDR_OPS_MSK, opcode);
+ cmd->sq_msg.hdr.msg_size = FIELD_PREP(RM_CMD_SQ_HDR_SIZE_MSK, size);
+
+ id = ida_alloc_range(&rm_cmd_ids, RM_CMD_ID_MIN, RM_CMD_ID_MAX, GFP_KERNEL);
+ if (id < 0) {
+ vdev_err(rdev->vdev, "Failed to alloc cmd ID: %d", id);
+ ret = id;
+ goto error;
+ }
+ cmd->sq_msg.hdr.id = id;
+
+ init_completion(&cmd->executed);
+
+ *cmd_ptr = cmd;
+ return 0;
+error:
+ kfree(cmd);
+ return ret;
+}
+
+static int rm_queue_verify(struct rm_device *rdev)
+{
+ struct versal_pci_device *vdev = rdev->vdev;
+ struct rm_cmd_cq_identify *result;
+ struct rm_cmd *cmd;
+ u32 major, minor;
+ int ret;
+
+ ret = rm_queue_create_cmd(rdev, RM_QUEUE_OP_IDENTIFY, &cmd);
+ if (ret)
+ return ret;
+
+ ret = rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT);
+ if (ret)
+ goto error;
+
+ result = &cmd->cq_msg.data.identify;
+ major = result->major;
+ minor = result->minor;
+ vdev_dbg(vdev, "VMR version %d.%d", major, minor);
+ if (!major) {
+ vdev_err(vdev, "VMR version is unsupported");
+ ret = -EOPNOTSUPP;
+ }
+
+error:
+ rm_queue_destroy_cmd(cmd);
+ return ret;
+}
+
+static int rm_check_apu_status(struct rm_device *rdev, bool *status)
+{
+ struct rm_cmd_cq_control *result;
+ struct rm_cmd *cmd;
+ int ret;
+
+ ret = rm_queue_create_cmd(rdev, RM_QUEUE_OP_VMR_CONTROL, &cmd);
+ if (ret)
+ return ret;
+
+ ret = rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT);
+ if (ret)
+ goto error;
+
+ result = &cmd->cq_msg.data.ctrl;
+ *status = FIELD_GET(RM_CMD_VMR_CONTROL_PS_MASK, result->status);
+
+ rm_queue_destroy_cmd(cmd);
+ return 0;
+
+error:
+ rm_queue_destroy_cmd(cmd);
+ return ret;
+}
+
+static int rm_download_apu_fw(struct rm_device *rdev, char *data, ssize_t size)
+{
+ struct rm_cmd *cmd;
+ int ret;
+
+ ret = rm_queue_create_cmd(rdev, RM_QUEUE_OP_LOAD_APU_FW, &cmd);
+ if (ret)
+ return ret;
+
+ ret = rm_queue_data_init(cmd, data, size);
+ if (ret)
+ goto done;
+
+ ret = rm_queue_send_cmd(cmd, RM_CMD_WAIT_DOWNLOAD_TIMEOUT);
+
+done:
+ rm_queue_destroy_cmd(cmd);
+ return ret;
+}
+
+int rm_queue_boot_apu(struct rm_device *rdev)
+{
+ char *bin = "xilinx/xrt-versal-apu.xsabin";
+ const struct firmware *fw = NULL;
+ bool status;
+ int ret;
+
+ ret = rm_check_apu_status(rdev, &status);
+ if (ret) {
+ vdev_err(rdev->vdev, "Failed to get APU status");
+ return ret;
+ }
+
+ if (status) {
+ vdev_dbg(rdev->vdev, "APU online. Skipping APU FW download");
+ return 0;
+ }
+
+ ret = request_firmware(&fw, bin, &rdev->vdev->pdev->dev);
+ if (ret) {
+ vdev_warn(rdev->vdev, "Request APU FW %s failed %d", bin, ret);
+ return ret;
+ }
+
+ vdev_dbg(rdev->vdev, "Starting... APU FW download");
+ ret = rm_download_apu_fw(rdev, (char *)fw->data, fw->size);
+ vdev_dbg(rdev->vdev, "Finished... APU FW download %d", ret);
+
+ if (ret)
+ vdev_err(rdev->vdev, "Failed to download APU FW, ret:%d", ret);
+
+ release_firmware(fw);
+
+ return ret;
+}
+
+static void rm_check_health(struct work_struct *w)
+{
+ struct rm_device *rdev = to_rdev_health_monitor(w);
+ u32 max_len = PAGE_SIZE;
+ struct rm_cmd *cmd;
+ int ret;
+
+ ret = rm_queue_create_cmd(rdev, RM_QUEUE_OP_GET_LOG_PAGE, &cmd);
+ if (ret)
+ return;
+
+ ret = rm_queue_payload_init(cmd, RM_CMD_LOG_PAGE_AXI_TRIP_STATUS);
+ if (ret)
+ goto destroy_cmd;
+
+ ret = rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT);
+ if (ret == -ETIME || ret == -EINVAL)
+ goto payload_fini;
+
+ if (ret) {
+ u32 log_len = cmd->cq_msg.data.page.len;
+
+ if (log_len > max_len) {
+ vdev_warn(rdev->vdev, "msg size %d is greater than requested %d",
+ log_len, max_len);
+ log_len = max_len;
+ }
+
+ if (log_len) {
+ char *buffer = vzalloc(log_len);
+
+ if (!buffer)
+ goto payload_fini;
+
+ ret = rm_queue_copy_response(cmd, buffer, log_len);
+ if (ret) {
+ vfree(buffer);
+ goto payload_fini;
+ }
+
+ vdev_err(rdev->vdev, "%s", buffer);
+ vfree(buffer);
+
+ } else {
+ vdev_err(rdev->vdev, "firewall check ret%d", ret);
+ }
+
+ rdev->firewall_tripped = 1;
+ }
+
+payload_fini:
+ rm_queue_payload_fini(cmd);
+destroy_cmd:
+ rm_queue_destroy_cmd(cmd);
+
+ vdev_dbg(rdev->vdev, "check result: %d", ret);
+}
+
+static void rm_sched_health_check(struct timer_list *t)
+{
+ struct rm_device *rdev = to_rdev_health_timer(t);
+
+ if (rdev->firewall_tripped) {
+ vdev_err(rdev->vdev, "Firewall tripped, health check paused. Please reset card");
+ return;
+ }
+ /* Schedule a work in the general workqueue */
+ schedule_work(&rdev->health_monitor);
+ /* Periodic timer */
+ mod_timer(&rdev->health_timer, jiffies + RM_HEALTH_CHECK_TIMER);
+}
+
+static void rm_uninstall_health_monitor(struct rm_device *rdev)
+{
+ del_timer_sync(&rdev->health_timer);
+ cancel_work_sync(&rdev->health_monitor);
+}
+
+static void rm_install_health_monitor(struct rm_device *rdev)
+{
+ INIT_WORK(&rdev->health_monitor, &rm_check_health);
+ timer_setup(&rdev->health_timer, &rm_sched_health_check, 0);
+ mod_timer(&rdev->health_timer, jiffies + RM_HEALTH_CHECK_TIMER);
+}
+
+void versal_pci_rm_fini(struct rm_device *rdev)
+{
+ rm_uninstall_health_monitor(rdev);
+ rm_queue_fini(rdev);
+}
+
+struct rm_device *versal_pci_rm_init(struct versal_pci_device *vdev)
+{
+ struct rm_header *header;
+ struct rm_device *rdev;
+ u32 status;
+ int ret;
+
+ rdev = devm_kzalloc(&vdev->pdev->dev, sizeof(*rdev), GFP_KERNEL);
+ if (!rdev)
+ return ERR_PTR(-ENOMEM);
+
+ rdev->vdev = vdev;
+ header = &rdev->rm_metadata;
+
+ rm_shmem_bulk_read(rdev, RM_HDR_OFF, (u32 *)header, sizeof(*header));
+ if (header->magic != RM_HDR_MAGIC_NUM) {
+ vdev_err(vdev, "Invalid RM header 0x%x", header->magic);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ status = rm_shmem_read(rdev, header->status_off);
+ if (!status) {
+ vdev_err(vdev, "RM status %d is not ready", status);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ rdev->queue_buffer_size = header->data_end - header->data_start + 1;
+ rdev->queue_buffer_start = header->data_start;
+ rdev->queue_base = header->queue_base;
+
+ ret = rm_queue_init(rdev);
+ if (ret) {
+ vdev_err(vdev, "Failed to init cmd queue, ret %d", ret);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = rm_queue_verify(rdev);
+ if (ret) {
+ vdev_err(vdev, "Failed to verify cmd queue, ret %d", ret);
+ ret = -ENODEV;
+ goto queue_fini;
+ }
+
+ ret = rm_queue_boot_apu(rdev);
+ if (ret) {
+ vdev_err(vdev, "Failed to bringup APU, ret %d", ret);
+ ret = -ENODEV;
+ goto queue_fini;
+ }
+
+ rm_install_health_monitor(rdev);
+
+ return rdev;
+queue_fini:
+ rm_queue_fini(rdev);
+err:
+ return ERR_PTR(ret);
+}
+
+int rm_queue_get_fw_id(struct rm_device *rdev)
+{
+ struct rm_cmd *cmd;
+ int ret;
+
+ ret = rm_queue_create_cmd(rdev, RM_QUEUE_OP_GET_LOG_PAGE, &cmd);
+ if (ret)
+ return ret;
+
+ ret = rm_queue_payload_init(cmd, RM_CMD_LOG_PAGE_FW_ID);
+ if (ret)
+ goto destroy_cmd;
+
+ ret = rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT);
+ if (ret)
+ goto payload_fini;
+
+ ret = rm_queue_copy_response(cmd, rdev->vdev->fw_id, sizeof(rdev->vdev->fw_id));
+ if (ret)
+ goto payload_fini;
+
+ vdev_info(rdev->vdev, "fw_id %s", rdev->vdev->fw_id);
+
+payload_fini:
+ rm_queue_payload_fini(cmd);
+destroy_cmd:
+ rm_queue_destroy_cmd(cmd);
+
+ return ret;
+}
diff --git a/drivers/misc/amd/versal-pci-rm-service.h b/drivers/misc/amd/versal-pci-rm-service.h
index d2397a1a672c..57333bb1443c 100644
--- a/drivers/misc/amd/versal-pci-rm-service.h
+++ b/drivers/misc/amd/versal-pci-rm-service.h
@@ -206,4 +206,24 @@ struct rm_device {
__u32 firewall_tripped;
};
+/* rm service init api */
+struct rm_device *versal_pci_rm_init(struct versal_pci_device *vdev);
+void versal_pci_rm_fini(struct rm_device *rdev);
+
+/* rm services APIs */
+int rm_queue_create_cmd(struct rm_device *rdev, enum rm_queue_opcode opcode,
+ struct rm_cmd **cmd_ptr);
+void rm_queue_destroy_cmd(struct rm_cmd *cmd);
+
+int rm_queue_data_init(struct rm_cmd *cmd, const char *buffer, ssize_t size);
+void rm_queue_data_fini(struct rm_cmd *cmd);
+int rm_queue_get_fw_id(struct rm_device *rdev);
+int rm_queue_boot_apu(struct rm_device *rdev);
+
+/* rm bar register operation APIs */
+u32 rm_reg_read(struct rm_device *rdev, u32 offset);
+void rm_reg_write(struct rm_device *rdev, u32 offset, const u32 value);
+void rm_bulk_reg_read(struct rm_device *rdev, u32 offset, u32 *value, size_t size);
+void rm_bulk_reg_write(struct rm_device *rdev, u32 offset, const void *value, size_t size);
+
#endif /* __RM_SERVICE_H */
diff --git a/drivers/misc/amd/versal-pci.h b/drivers/misc/amd/versal-pci.h
index 33f0ef881a33..89f3590137ce 100644
--- a/drivers/misc/amd/versal-pci.h
+++ b/drivers/misc/amd/versal-pci.h
@@ -51,6 +51,7 @@ struct fw_info {
struct versal_pci_device {
struct pci_dev *pdev;
+ struct rm_device *rdev;
struct fw_info fw;
void __iomem *io_regs;
--
2.34.1
next prev parent reply other threads:[~2025-03-03 4:44 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-03 4:43 [PATCH V0 0/3] Add versal-pci driver Yidong Zhang
2025-03-03 4:43 ` [PATCH V0 1/3] drivers/misc/amd: Add new driver amd versal-pci Yidong Zhang
2025-03-03 4:43 ` [PATCH V0 2/3] drivers/misc/amd: Add remote queue service Yidong Zhang
2025-03-03 4:43 ` Yidong Zhang [this message]
2025-04-15 14:11 ` [PATCH V0 0/3] Add versal-pci driver Greg KH
2025-04-17 0:09 ` Yidong Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250303044313.679012-4-yidong.zhang@amd.com \
--to=yidong.zhang@amd.com \
--cc=arnd@arndb.de \
--cc=christophe.jaillet@wanadoo.fr \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizhi.hou@amd.com \
--cc=nishads@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.