summaryrefslogtreecommitdiff
path: root/drivers/firmware
diff options
context:
space:
mode:
authorMahesh Rao <mahesh.rao@altera.com>2025-10-27 17:54:42 +0300
committerDinh Nguyen <dinguyen@kernel.org>2025-11-13 15:32:58 +0300
commitec52379341a1209826c3e0ae53674393724d2071 (patch)
tree619ed156c65d383c5c53ba9f35ac2e0c59f1d187 /drivers/firmware
parentbcb9f4f0706147afc62c48533276a18fe7b8f354 (diff)
downloadlinux-ec52379341a1209826c3e0ae53674393724d2071.tar.xz
firmware: stratix10-svc: Add support for RSU commands in asynchronous framework
Integrate Remote System Update(RSU) service commands into the asynchronous framework for communicating with SDM. This allows the RSU commands to be processed asynchronously, improving the responsiveness of the Stratix10 service channel. The asynchronous framework now supports the following RSU commands: * COMMAND_RSU_GET_SPT_TABLE * COMMAND_RSU_STATUS * COMMAND_RSU_NOTIFY Signed-off-by: Mahesh Rao <mahesh.rao@altera.com> Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com> Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/stratix10-svc.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 14bfa36a58ed..3acfa067c5dd 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -90,6 +90,12 @@
#define STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(transaction_id) \
(FIELD_PREP(STRATIX10_TRANS_ID_FIELD, transaction_id))
+/* 10-bit mask for extracting the SDM status code */
+#define STRATIX10_SDM_STATUS_MASK GENMASK(9, 0)
+/* Macro to get the SDM mailbox error status */
+#define STRATIX10_GET_SDM_STATUS_CODE(status) \
+ (FIELD_GET(STRATIX10_SDM_STATUS_MASK, status))
+
typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long,
@@ -1273,6 +1279,16 @@ int stratix10_svc_async_send(struct stratix10_svc_chan *chan, void *msg,
STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(handle->transaction_id);
switch (p_msg->command) {
+ case COMMAND_RSU_GET_SPT_TABLE:
+ args.a0 = INTEL_SIP_SMC_ASYNC_RSU_GET_SPT;
+ break;
+ case COMMAND_RSU_STATUS:
+ args.a0 = INTEL_SIP_SMC_ASYNC_RSU_GET_ERROR_STATUS;
+ break;
+ case COMMAND_RSU_NOTIFY:
+ args.a0 = INTEL_SIP_SMC_ASYNC_RSU_NOTIFY;
+ args.a2 = p_msg->arg[0];
+ break;
default:
dev_err(ctrl->dev, "Invalid command ,%d\n", p_msg->command);
ret = -EINVAL;
@@ -1326,6 +1342,56 @@ deallocate_id:
return ret;
}
EXPORT_SYMBOL_GPL(stratix10_svc_async_send);
+
+/**
+ * stratix10_svc_async_prepare_response - Prepare the response data for
+ * an asynchronous transaction.
+ * @chan: Pointer to the service channel structure.
+ * @handle: Pointer to the asynchronous handler structure.
+ * @data: Pointer to the callback data structure.
+ *
+ * This function prepares the response data for an asynchronous transaction. It
+ * extracts the response data from the SMC response structure and stores it in
+ * the callback data structure. The function also logs the completion of the
+ * asynchronous transaction.
+ *
+ * Return: 0 on success, -ENOENT if the command is invalid
+ */
+static int stratix10_svc_async_prepare_response(struct stratix10_svc_chan *chan,
+ struct stratix10_svc_async_handler *handle,
+ struct stratix10_svc_cb_data *data)
+{
+ struct stratix10_svc_client_msg *p_msg =
+ (struct stratix10_svc_client_msg *)handle->msg;
+ struct stratix10_svc_controller *ctrl = chan->ctrl;
+
+ data->status = STRATIX10_GET_SDM_STATUS_CODE(handle->res.a1);
+
+ switch (p_msg->command) {
+ case COMMAND_RSU_NOTIFY:
+ break;
+ case COMMAND_RSU_GET_SPT_TABLE:
+ data->kaddr1 = (void *)&handle->res.a2;
+ data->kaddr2 = (void *)&handle->res.a3;
+ break;
+ case COMMAND_RSU_STATUS:
+ /* COMMAND_RSU_STATUS has more elements than the cb_data
+ * can acomodate, so passing the response structure to the
+ * response function to be handled before done command is
+ * executed by the client.
+ */
+ data->kaddr1 = (void *)&handle->res;
+ break;
+
+ default:
+ dev_alert(ctrl->dev, "Invalid command\n ,%d", p_msg->command);
+ return -ENOENT;
+ }
+ dev_dbg(ctrl->dev, "Async message completed transaction_id 0x%02x\n",
+ handle->transaction_id);
+ return 0;
+}
+
/**
* stratix10_svc_async_poll - Polls the status of an asynchronous
* transaction.
@@ -1355,6 +1421,7 @@ int stratix10_svc_async_poll(struct stratix10_svc_chan *chan,
struct stratix10_svc_controller *ctrl;
struct stratix10_async_ctrl *actrl;
struct stratix10_async_chan *achan;
+ int ret;
if (!chan || !tx_handle || !data)
return -EINVAL;
@@ -1386,6 +1453,11 @@ int stratix10_svc_async_poll(struct stratix10_svc_chan *chan,
memset(data, 0, sizeof(*data));
if (handle->res.a0 == INTEL_SIP_SMC_STATUS_OK) {
+ ret = stratix10_svc_async_prepare_response(chan, handle, data);
+ if (ret) {
+ dev_err(ctrl->dev, "Error in preparation of response,%d\n", ret);
+ WARN_ON_ONCE(1);
+ }
return 0;
} else if (handle->res.a0 == INTEL_SIP_SMC_STATUS_BUSY) {
dev_dbg(ctrl->dev, "async message is still in progress\n");