From nobody Sun Dec 14 06:18:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AD712C235A; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; cv=none; b=p45F/ZRBwQKLcVMWbI48WCbVVVIp/1jAcV6zRNGjRCPR7bpqcJScdMhIvPE/PRApwMcO3HBI/uQVfEd53X5s4avjqMXUPwVL9glf1+sWocvdt0x3PbGv/rrvt5OkG6fL/mWvSZaqNzP/m8G1j6kI2Uu2q8zu4ekU6hzgMHnDTuo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; c=relaxed/simple; bh=630iEkx+YNPZ4//7+pyREH3IJH/Xcs2Vt1WdwrNDa48=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CdePA/yETdp05aTvIaIHsvZFT/+/GbYbXVNKHPB6hEj0NhMBoYd7cOx0bSa3IPflEh5/rWT1irTkVEGrnSMHmOUcDcrqx9oLn83nzxtbtwXN4dxCDFnJaRtap2B78VBNmpHd+kIYRcEw3liDCJci2uh3wzX2HDZ1Y5Vya3lAoQc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SLf/iieQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SLf/iieQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1EE3AC4AF0D; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761576957; bh=630iEkx+YNPZ4//7+pyREH3IJH/Xcs2Vt1WdwrNDa48=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=SLf/iieQa14Vwm91zPmbOWMMaOIKdUMgSiNNkJj89s3n+LtlJRJFt4lkP00+wv+oL qqhx8hLl0JfZT+geudIS8DP0Q+rtLYK5T+X+QAR2arzaGHn6VJ3oqYFgLWMrqpGHW7 HfGVzszEyLH6gnRX0GEIRi0VRLmpLAFXe4UNJ1cjYtdUwNBpfdqPBtoplmSvBSOrZv Cs9w6/jWBqXsmJ0h6fO9U0icMpG52fvF7HxxUhH5sG+tZzEHr13gkId9HVtoVGbsJF 0dAIb04FYsX9XUOUZwvsJhFzevChOasQlak6hRBlOuSC2y9+UZZ9MCP1Jg1WZRkG6g 7a3Zl9zGlDWIw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E1E5CCF9E5; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) From: Mahesh Rao via B4 Relay Date: Mon, 27 Oct 2025 22:54:40 +0800 Subject: [PATCH v7 1/4] firmware: stratix10-svc: Add mutex in stratix10 memory management Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251027-sip_svc_upstream-v7-1-6e9ab26d7480@altera.com> References: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> In-Reply-To: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> To: Dinh Nguyen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Mahesh Rao , Richard Gong , Alan Tull , Greg Kroah-Hartman Cc: Matthew Gerlach , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1761576953; l=2638; i=mahesh.rao@altera.com; s=20250107; h=from:subject:message-id; bh=0fTSklXVsq/tvEDKt4nwGZPVgU/SjDg904S5A3vTUzI=; b=ecuWGXs43wXI+9Bh2xWvfRJUM+kPx/zUXNvychsYFnvV49ueaoXO8Cdpq94DPlRhLoToRY96t sGF43Tpcz7sCqsMiy1b9DZaDxw8zteSJkjYposllXmr5fq8+ndhBbqb X-Developer-Key: i=mahesh.rao@altera.com; a=ed25519; pk=tQiFUzoKxHrQLDtWeEeaeTeJTl/UfclUHWZy1fjSiyg= X-Endpoint-Received: by B4 Relay for mahesh.rao@altera.com/20250107 with auth_id=337 X-Original-From: Mahesh Rao Reply-To: mahesh.rao@altera.com From: Mahesh Rao Add mutex lock to stratix10_svc_allocate_memory and stratix10_svc_free_memory for thread safety. This prevents race conditions and ensures proper synchronization during memory operations. This is required for parallel communication with the Stratix10 service channel. Fixes: 7ca5ce896524f ("firmware: add Intel Stratix10 service layer driver") Signed-off-by: Mahesh Rao Reviewed-by: Matthew Gerlach Signed-off-by: Dinh Nguyen --- drivers/firmware/stratix10-svc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-= svc.c index 5a32c1054bee1d05809bbe828880ce4f30534c96..9372a17d89b7ceccee5e6efa233= 03175caddd038 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017-2018, Intel Corporation + * Copyright (C) 2025, Altera Corporation */ =20 #include @@ -172,6 +173,12 @@ struct stratix10_svc_chan { static LIST_HEAD(svc_ctrl); static LIST_HEAD(svc_data_mem); =20 +/** + * svc_mem_lock protects access to the svc_data_mem list for + * concurrent multi-client operations + */ +static DEFINE_MUTEX(svc_mem_lock); + /** * svc_pa_to_va() - translate physical address to virtual address * @addr: to be translated physical address @@ -184,6 +191,7 @@ static void *svc_pa_to_va(unsigned long addr) struct stratix10_svc_data_mem *pmem; =20 pr_debug("claim back P-addr=3D0x%016x\n", (unsigned int)addr); + guard(mutex)(&svc_mem_lock); list_for_each_entry(pmem, &svc_data_mem, node) if (pmem->paddr =3D=3D addr) return pmem->vaddr; @@ -1002,6 +1010,7 @@ int stratix10_svc_send(struct stratix10_svc_chan *cha= n, void *msg) p_data->flag =3D ct->flags; } } else { + guard(mutex)(&svc_mem_lock); list_for_each_entry(p_mem, &svc_data_mem, node) if (p_mem->vaddr =3D=3D p_msg->payload) { p_data->paddr =3D p_mem->paddr; @@ -1084,6 +1093,7 @@ void *stratix10_svc_allocate_memory(struct stratix10_= svc_chan *chan, if (!pmem) return ERR_PTR(-ENOMEM); =20 + guard(mutex)(&svc_mem_lock); va =3D gen_pool_alloc(genpool, s); if (!va) return ERR_PTR(-ENOMEM); @@ -1112,6 +1122,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory); void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kadd= r) { struct stratix10_svc_data_mem *pmem; + guard(mutex)(&svc_mem_lock); =20 list_for_each_entry(pmem, &svc_data_mem, node) if (pmem->vaddr =3D=3D kaddr) { --=20 2.43.7 From nobody Sun Dec 14 06:18:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6ADE22C3768; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; cv=none; b=VakldoCcditYlcAlczFWPKCwS0HZinvj1wpE+kWMeGC2tvG5QxXjF6ztg/FnNCrLSkm+EhLfpe6VnWGHIVi2BlygDZUoWs6mGrpZHt4/gbsGKBIUq3+6k3yVaxsNVgYbnd6GXsCpgNIT6ziiT77/3ZKo6kZ2emxnL95AnlFjwFk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; c=relaxed/simple; bh=HzWXstXm/wizP2YfFb8eQYqCozNverakOdrV3DCgg60=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E1WNZpWWO+er7dIDb5H5uxssjUyDb3hBBjfzJ28xYJ1+L/Dmon/kOvF0/bxWOvxh67HcGm9Z8AM1rGSDF0wpvIEXfKOep3Bwoo4692IQSG7DMOrlIe9bkDkT4mq9Ur4AJ6dhpk0H+o0aZAxBVE6ytsSj4h2ELrYASYeed27ZR5k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rMAUDiX3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rMAUDiX3" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2CEC6C4CEFF; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761576957; bh=HzWXstXm/wizP2YfFb8eQYqCozNverakOdrV3DCgg60=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=rMAUDiX36Q1XETkUAGVxycs4SheF2dByRl4OlEH3nItlS7Yw1YlC8hUJhCMrTRYF/ 3DGL96lvBzvOAJ51+BW85yCVh8EGyappsY/1MYrpgtNlg+8mln0QgIIN1zKUJHG/Ky 4NhpyRxMC5GmQL8kL37QeyNo/6OTl7ih3OOuxJ6e5t17dTgQCrP87SIjFXc6CmmUqq YTyzSfSmqbNb02dD4PcyW5PI69tF25mUROUzQYabfOdLg6E8HFET0VeIl1N6RJyGPx 0dxQ+Bj3z6UDI7EfFGLB9bpfCTTNB+LS88v1xUQZRphgnchBMo5pCzEWmFwMuD2ZuD wgAqppTV/mWvQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22946CCF9EE; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) From: Mahesh Rao via B4 Relay Date: Mon, 27 Oct 2025 22:54:41 +0800 Subject: [PATCH v7 2/4] firmware: stratix10-svc: Add support for async communication Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251027-sip_svc_upstream-v7-2-6e9ab26d7480@altera.com> References: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> In-Reply-To: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> To: Dinh Nguyen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Mahesh Rao , Richard Gong , Alan Tull , Greg Kroah-Hartman Cc: Matthew Gerlach , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1761576953; l=33956; i=mahesh.rao@altera.com; s=20250107; h=from:subject:message-id; bh=s83UjhGW41rDa7RL7x5/+KvnO4YuRyXIoAeM04Iphcw=; b=zOcPTeIE98DmBN87JROyO4lKXbgGe3GmSmLqQ/bTdIwyaXpTHPf9ckV5fCbDlJmsdSjX73Fom pzP4l8kAmfBBjPf0bvmimuSxJ10rwovyHKBHsMNIFGBO4JojxHGuccn X-Developer-Key: i=mahesh.rao@altera.com; a=ed25519; pk=tQiFUzoKxHrQLDtWeEeaeTeJTl/UfclUHWZy1fjSiyg= X-Endpoint-Received: by B4 Relay for mahesh.rao@altera.com/20250107 with auth_id=337 X-Original-From: Mahesh Rao Reply-To: mahesh.rao@altera.com From: Mahesh Rao Introduce support for asynchronous communication with the Stratix10 service channel. Define new structures to enable asynchronous messaging with the Secure Device Manager (SDM). Add and remove asynchronous support for existing channels. Implement initialization and cleanup routines for the asynchronous framework. Enable sending and polling of messages to the SDM asynchronously. The new public functions added are: - stratix10_svc_add_async_client: Adds a client to the service channel. - stratix10_svc_remove_async_client: Removes an asynchronous client from the service channel. - stratix10_svc_async_send: Sends an asynchronous message to the SDM mailbox in EL3 secure firmware. - stratix10_svc_async_poll: Polls the status of an asynchronous service request in EL3 secure firmware. - stratix10_svc_async_done: Marks an asynchronous transaction as complete and frees up the resources. These changes enhance the functionality of the Stratix10 service channel by allowing for more efficient and flexible communication with the firmware. Signed-off-by: Mahesh Rao Reviewed-by: Matthew Gerlach Signed-off-by: Dinh Nguyen --- drivers/firmware/stratix10-svc.c | 656 +++++++++++++++++= +++- include/linux/firmware/intel/stratix10-smc.h | 25 + .../linux/firmware/intel/stratix10-svc-client.h | 88 +++ 3 files changed, 765 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-= svc.c index 9372a17d89b7ceccee5e6efa23303175caddd038..14bfa36a58ed38a19de9f541428= 27a29ced0851d 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -4,9 +4,12 @@ * Copyright (C) 2025, Altera Corporation */ =20 +#include #include #include #include +#include +#include #include #include #include @@ -44,6 +47,49 @@ #define STRATIX10_RSU "stratix10-rsu" #define INTEL_FCS "intel-fcs" =20 +/* Maximum number of SDM client IDs. */ +#define MAX_SDM_CLIENT_IDS 16 +/* Client ID for SIP Service Version 1. */ +#define SIP_SVC_V1_CLIENT_ID 0x1 +/* Maximum number of SDM job IDs. */ +#define MAX_SDM_JOB_IDS 16 +/* Number of bits used for asynchronous transaction hashing. */ +#define ASYNC_TRX_HASH_BITS 3 +/** + * Total number of transaction IDs, which is a combination of + * client ID and job ID. + */ +#define TOTAL_TRANSACTION_IDS \ + (MAX_SDM_CLIENT_IDS * MAX_SDM_JOB_IDS) + +/* Minimum major version of the ATF for Asynchronous transactions. */ +#define ASYNC_ATF_MINIMUM_MAJOR_VERSION 0x3 +/* Minimum minor version of the ATF for Asynchronous transactions.*/ +#define ASYNC_ATF_MINIMUM_MINOR_VERSION 0x0 + +/* Job ID field in the transaction ID */ +#define STRATIX10_JOB_FIELD GENMASK(3, 0) +/* Client ID field in the transaction ID */ +#define STRATIX10_CLIENT_FIELD GENMASK(7, 4) +/* Transaction ID mask for Stratix10 service layer */ +#define STRATIX10_TRANS_ID_FIELD GENMASK(7, 0) + +/* Macro to extract the job ID from a transaction ID. */ +#define STRATIX10_GET_JOBID(transaction_id) \ + (FIELD_GET(STRATIX10_JOB_FIELD, transaction_id)) +/* Macro to set the job ID in a transaction ID. */ +#define STRATIX10_SET_JOBID(jobid) \ + (FIELD_PREP(STRATIX10_JOB_FIELD, jobid)) +/* Macro to set the client ID in a transaction ID. */ +#define STRATIX10_SET_CLIENTID(clientid) \ + (FIELD_PREP(STRATIX10_CLIENT_FIELD, clientid)) +/* Macro to set a transaction ID using a client ID and a job ID. */ +#define STRATIX10_SET_TRANSACTIONID(clientid, jobid) \ + (STRATIX10_SET_CLIENTID(clientid) | STRATIX10_SET_JOBID(jobid)) +/* Macro to set a transaction ID for SIP SMC Async transactions */ +#define STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(transaction_id) \ + (FIELD_PREP(STRATIX10_TRANS_ID_FIELD, transaction_id)) + typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, @@ -64,7 +110,7 @@ struct stratix10_svc { * @sync_complete: state for a completion * @addr: physical address of shared memory block * @size: size of shared memory block - * @invoke_fn: function to issue secure monitor or hypervisor call + * @invoke_fn: service clients to handle secure monitor or hypervisor calls * * This struct is used to save physical address and size of shared memory * block. The shared memory blocked is allocated by secure monitor software @@ -122,6 +168,74 @@ struct stratix10_svc_data { u64 arg[3]; }; =20 +/** + * struct stratix10_svc_async_handler - Asynchronous handler for Stratix10 + * service layer + * @transaction_id: Unique identifier for the transaction + * @achan: Pointer to the asynchronous channel structure + * @cb_arg: Argument to be passed to the callback function + * @cb: Callback function to be called upon completion + * @msg: Pointer to the client message structure + * @next: Node in the hash list + * @res: Response structure to store result from the secure firmware + * + * This structure is used to handle asynchronous transactions in the + * Stratix10 service layer. It maintains the necessary information + * for processing and completing asynchronous requests. + */ + +struct stratix10_svc_async_handler { + u8 transaction_id; + struct stratix10_async_chan *achan; + void *cb_arg; + async_callback_t cb; + struct stratix10_svc_client_msg *msg; + struct hlist_node next; + struct arm_smccc_1_2_regs res; +}; + +/** + * struct stratix10_async_chan - Structure representing an asynchronous ch= annel + * @async_client_id: Unique client identifier for the asynchronous operati= on + * @job_id_pool: Pointer to the job ID pool associated with this channel + */ + +struct stratix10_async_chan { + unsigned long async_client_id; + struct ida job_id_pool; +}; + +/** + * struct stratix10_async_ctrl - Control structure for Stratix10 + * asynchronous operations + * @initialized: Flag indicating whether the control structure has + * been initialized + * @invoke_fn: Function pointer for invoking Stratix10 service calls + * to EL3 secure firmware + * @async_id_pool: Pointer to the ID pool used for asynchronous + * operations + * @common_achan_refcount: Atomic reference count for the common + * asynchronous channel usage + * @common_async_chan: Pointer to the common asynchronous channel + * structure + * @trx_list_lock: Spinlock for protecting the transaction list + * operations + * @trx_list: Hash table for managing asynchronous transactions + */ + +struct stratix10_async_ctrl { + bool initialized; + void (*invoke_fn)(struct stratix10_async_ctrl *actrl, + const struct arm_smccc_1_2_regs *args, + struct arm_smccc_1_2_regs *res); + struct ida async_id_pool; + atomic_t common_achan_refcount; + struct stratix10_async_chan *common_async_chan; + /* spinlock to protect trx_list hash table */ + spinlock_t trx_list_lock; + DECLARE_HASHTABLE(trx_list, ASYNC_TRX_HASH_BITS); +}; + /** * struct stratix10_svc_controller - service controller * @dev: device @@ -135,6 +249,7 @@ struct stratix10_svc_data { * @complete_status: state for completion * @svc_fifo_lock: protect access to service message data queue * @invoke_fn: function to issue secure monitor call or hypervisor call + * @actrl: async control structure * * This struct is used to create communication channels for service client= s, to * handle secure monitor or hypervisor call. @@ -151,6 +266,7 @@ struct stratix10_svc_controller { struct completion complete_status; spinlock_t svc_fifo_lock; svc_invoke_fn *invoke_fn; + struct stratix10_async_ctrl actrl; }; =20 /** @@ -159,15 +275,17 @@ struct stratix10_svc_controller { * @scl: pointer to service client which owns the channel * @name: service client name associated with the channel * @lock: protect access to the channel + * @async_chan: reference to asynchronous channel object for this channel * - * This struct is used by service client to communicate with service layer= , each - * service client has its own channel created by service controller. + * This struct is used by service client to communicate with service layer. + * Each service client has its own channel created by service controller. */ struct stratix10_svc_chan { struct stratix10_svc_controller *ctrl; struct stratix10_svc_client *scl; char *name; spinlock_t lock; + struct stratix10_async_chan *async_chan; }; =20 static LIST_HEAD(svc_ctrl); @@ -942,6 +1060,525 @@ struct stratix10_svc_chan *stratix10_svc_request_cha= nnel_byname( } EXPORT_SYMBOL_GPL(stratix10_svc_request_channel_byname); =20 +/** + * stratix10_svc_add_async_client - Add an asynchronous client to the + * Stratix10 service channel. + * @chan: Pointer to the Stratix10 service channel structure. + * @use_unique_clientid: Boolean flag indicating whether to use a + * unique client ID. + * + * This function adds an asynchronous client to the specified + * Stratix10 service channel. If the `use_unique_clientid` flag is + * set to true, a unique client ID is allocated for the asynchronous + * channel. Otherwise, a common asynchronous channel is used. + * + * Return: 0 on success, or a negative error code on failure: + * -EINVAL if the channel is NULL or the async controller is + * not initialized. + * -EALREADY if the async channel is already allocated. + * -ENOMEM if memory allocation fails. + * Other negative values if ID allocation fails. + */ +int stratix10_svc_add_async_client(struct stratix10_svc_chan *chan, + bool use_unique_clientid) +{ + struct stratix10_svc_controller *ctrl; + struct stratix10_async_ctrl *actrl; + struct stratix10_async_chan *achan; + int ret =3D 0; + + if (!chan) + return -EINVAL; + + ctrl =3D chan->ctrl; + actrl =3D &ctrl->actrl; + + if (!actrl->initialized) { + dev_err(ctrl->dev, "Async controller not initialized\n"); + return -EINVAL; + } + + if (chan->async_chan) { + dev_err(ctrl->dev, "async channel already allocated\n"); + return -EALREADY; + } + + if (use_unique_clientid && + atomic_read(&actrl->common_achan_refcount) > 0) { + chan->async_chan =3D actrl->common_async_chan; + atomic_inc(&actrl->common_achan_refcount); + return 0; + } + + achan =3D kzalloc(sizeof(*achan), GFP_KERNEL); + if (!achan) + return -ENOMEM; + + ida_init(&achan->job_id_pool); + + ret =3D ida_alloc_max(&actrl->async_id_pool, MAX_SDM_CLIENT_IDS, + GFP_KERNEL); + if (ret < 0) { + dev_err(ctrl->dev, + "Failed to allocate async client id\n"); + ida_destroy(&achan->job_id_pool); + kfree(achan); + return ret; + } + + achan->async_client_id =3D ret; + chan->async_chan =3D achan; + + if (use_unique_clientid && + atomic_read(&actrl->common_achan_refcount) =3D=3D 0) { + actrl->common_async_chan =3D achan; + atomic_inc(&actrl->common_achan_refcount); + } + + return 0; +} +EXPORT_SYMBOL_GPL(stratix10_svc_add_async_client); + +/** + * stratix10_svc_remove_async_client - Remove an asynchronous client + * from the Stratix10 service + * channel. + * @chan: Pointer to the Stratix10 service channel structure. + * + * This function removes an asynchronous client associated with the + * given service channel. It checks if the channel and the + * asynchronous channel are valid, and then proceeds to decrement + * the reference count for the common asynchronous channel if + * applicable. If the reference count reaches zero, it destroys the + * job ID pool and deallocates the asynchronous client ID. For + * non-common asynchronous channels, it directly destroys the job ID + * pool, deallocates the asynchronous client ID, and frees the + * memory allocated for the asynchronous channel. + * + * Return: 0 on success, -EINVAL if the channel or asynchronous + * channel is invalid. + */ +int stratix10_svc_remove_async_client(struct stratix10_svc_chan *chan) +{ + struct stratix10_svc_controller *ctrl; + struct stratix10_async_ctrl *actrl; + struct stratix10_async_chan *achan; + + if (!chan) + return -EINVAL; + + ctrl =3D chan->ctrl; + actrl =3D &ctrl->actrl; + achan =3D chan->async_chan; + + if (!achan) { + dev_err(ctrl->dev, "async channel not allocated\n"); + return -EINVAL; + } + + if (achan =3D=3D actrl->common_async_chan) { + atomic_dec(&actrl->common_achan_refcount); + if (atomic_read(&actrl->common_achan_refcount) =3D=3D 0) { + ida_destroy(&achan->job_id_pool); + ida_free(&actrl->async_id_pool, + achan->async_client_id); + kfree(achan); + actrl->common_async_chan =3D NULL; + } + } else { + ida_destroy(&achan->job_id_pool); + ida_free(&actrl->async_id_pool, achan->async_client_id); + kfree(achan); + } + chan->async_chan =3D NULL; + + return 0; +} +EXPORT_SYMBOL_GPL(stratix10_svc_remove_async_client); + +/** + * stratix10_svc_async_send - Send an asynchronous message to the + * Stratix10 service + * @chan: Pointer to the service channel structure + * @msg: Pointer to the message to be sent + * @handler: Pointer to the handler for the asynchronous message + * used by caller for later reference. + * @cb: Callback function to be called upon completion + * @cb_arg: Argument to be passed to the callback function + * + * This function sends an asynchronous message to the SDM mailbox in + * EL3 secure firmware. It performs various checks and setups, + * including allocating a job ID, setting up the transaction ID and + * packaging it to El3 firmware. The function handles different + * commands by setting up the appropriate arguments for the SMC call. + * If the SMC call is successful, the handler is set up and the + * function returns 0. If the SMC call fails, appropriate error + * handling is performed along with cleanup of resources. + * + * Return: 0 on success, -EINVAL for invalid argument, -ENOMEM if + * memory is not available, -EAGAIN if EL3 firmware is busy, -EBADF + * if the message is rejected by EL3 firmware and -EIO on other + * errors from EL3 firmware. + */ +int stratix10_svc_async_send(struct stratix10_svc_chan *chan, void *msg, + void **handler, async_callback_t cb, void *cb_arg) +{ + struct arm_smccc_1_2_regs args =3D { 0 }, res =3D { 0 }; + struct stratix10_svc_async_handler *handle =3D NULL; + struct stratix10_svc_client_msg *p_msg =3D + (struct stratix10_svc_client_msg *)msg; + struct stratix10_svc_controller *ctrl; + struct stratix10_async_ctrl *actrl; + struct stratix10_async_chan *achan; + int ret =3D 0; + + if (!chan || !msg || !handler) + return -EINVAL; + + achan =3D chan->async_chan; + ctrl =3D chan->ctrl; + actrl =3D &ctrl->actrl; + + if (!actrl->initialized) { + dev_err(ctrl->dev, "Async controller not initialized\n"); + return -EINVAL; + } + + if (!achan) { + dev_err(ctrl->dev, "Async channel not allocated\n"); + return -EINVAL; + } + + handle =3D kzalloc(sizeof(*handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + ret =3D ida_alloc_max(&achan->job_id_pool, MAX_SDM_JOB_IDS, + GFP_KERNEL); + if (ret < 0) { + dev_err(ctrl->dev, "Failed to allocate job id\n"); + kfree(handle); + return -ENOMEM; + } + + handle->transaction_id =3D + STRATIX10_SET_TRANSACTIONID(achan->async_client_id, ret); + handle->cb =3D cb; + handle->msg =3D p_msg; + handle->cb_arg =3D cb_arg; + handle->achan =3D achan; + + /*set the transaction jobid in args.a1*/ + args.a1 =3D + STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(handle->transaction_id); + + switch (p_msg->command) { + default: + dev_err(ctrl->dev, "Invalid command ,%d\n", p_msg->command); + ret =3D -EINVAL; + goto deallocate_id; + } + + /** + * There is a chance that during the execution of async_send() + * in one core, an interrupt might be received in another core; + * to mitigate this we are adding the handle to the DB and then + * send the smc call. If the smc call is rejected or busy then + * we will deallocate the handle for the client to retry again. + */ + scoped_guard(spinlock_bh, &actrl->trx_list_lock) { + hash_add(actrl->trx_list, &handle->next, + handle->transaction_id); + } + + actrl->invoke_fn(actrl, &args, &res); + + switch (res.a0) { + case INTEL_SIP_SMC_STATUS_OK: + dev_dbg(ctrl->dev, + "Async message sent with transaction_id 0x%02x\n", + handle->transaction_id); + *handler =3D handle; + return 0; + case INTEL_SIP_SMC_STATUS_BUSY: + dev_warn(ctrl->dev, "Mailbox is busy, try after some time\n"); + ret =3D -EAGAIN; + break; + case INTEL_SIP_SMC_STATUS_REJECTED: + dev_err(ctrl->dev, "Async message rejected\n"); + ret =3D -EBADF; + break; + default: + dev_err(ctrl->dev, + "Failed to send async message ,got status as %ld\n", + res.a0); + ret =3D -EIO; + } + + scoped_guard(spinlock_bh, &actrl->trx_list_lock) { + hash_del(&handle->next); + } + +deallocate_id: + ida_free(&achan->job_id_pool, + STRATIX10_GET_JOBID(handle->transaction_id)); + kfree(handle); + return ret; +} +EXPORT_SYMBOL_GPL(stratix10_svc_async_send); +/** + * stratix10_svc_async_poll - Polls the status of an asynchronous + * transaction. + * @chan: Pointer to the service channel structure. + * @tx_handle: Handle to the transaction being polled. + * @data: Pointer to the callback data structure. + * + * This function polls the status of an asynchronous transaction + * identified by the given transaction handle. It ensures that the + * necessary structures are initialized and valid before proceeding + * with the poll operation. The function sets up the necessary + * arguments for the SMC call, invokes the call, and prepares the + * response data if the call is successful. If the call fails, the + * function returns the error mapped to the SVC status error. + * + * Return: 0 on success, -EINVAL if any input parameter is invalid, + * -EAGAIN if the transaction is still in progress, + * -EPERM if the command is invalid, or other negative + * error codes on failure. + */ +int stratix10_svc_async_poll(struct stratix10_svc_chan *chan, + void *tx_handle, + struct stratix10_svc_cb_data *data) +{ + struct stratix10_svc_async_handler *handle; + struct arm_smccc_1_2_regs args =3D { 0 }; + struct stratix10_svc_controller *ctrl; + struct stratix10_async_ctrl *actrl; + struct stratix10_async_chan *achan; + + if (!chan || !tx_handle || !data) + return -EINVAL; + + ctrl =3D chan->ctrl; + actrl =3D &ctrl->actrl; + achan =3D chan->async_chan; + + if (!achan) { + dev_err(ctrl->dev, "Async channel not allocated\n"); + return -EINVAL; + } + + handle =3D (struct stratix10_svc_async_handler *)tx_handle; + scoped_guard(spinlock_bh, &actrl->trx_list_lock) { + if (!hash_hashed(&handle->next)) { + dev_err(ctrl->dev, "Invalid transaction handler"); + return -EINVAL; + } + } + + args.a0 =3D INTEL_SIP_SMC_ASYNC_POLL; + args.a1 =3D + STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(handle->transaction_id); + + actrl->invoke_fn(actrl, &args, &handle->res); + + /*clear data for response*/ + memset(data, 0, sizeof(*data)); + + if (handle->res.a0 =3D=3D INTEL_SIP_SMC_STATUS_OK) { + return 0; + } else if (handle->res.a0 =3D=3D INTEL_SIP_SMC_STATUS_BUSY) { + dev_dbg(ctrl->dev, "async message is still in progress\n"); + return -EAGAIN; + } + + dev_err(ctrl->dev, + "Failed to poll async message ,got status as %ld\n", + handle->res.a0); + return -EINVAL; +} +EXPORT_SYMBOL_GPL(stratix10_svc_async_poll); + +/** + * stratix10_svc_async_done - Completes an asynchronous transaction. + * @chan: Pointer to the service channel structure. + * @tx_handle: Handle to the transaction being completed. + * + * This function completes an asynchronous transaction identified by + * the given transaction handle. It ensures that the necessary + * structures are initialized and valid before proceeding with the + * completion operation. The function deallocates the transaction ID, + * frees the memory allocated for the handler, and removes the handler + * from the transaction list. + * + * Return: 0 on success, -EINVAL if any input parameter is invalid, + * or other negative error codes on failure. + */ +int stratix10_svc_async_done(struct stratix10_svc_chan *chan, void *tx_han= dle) +{ + struct stratix10_svc_async_handler *handle; + struct stratix10_svc_controller *ctrl; + struct stratix10_async_chan *achan; + struct stratix10_async_ctrl *actrl; + + if (!chan || !tx_handle) + return -EINVAL; + + ctrl =3D chan->ctrl; + achan =3D chan->async_chan; + actrl =3D &ctrl->actrl; + + if (!achan) { + dev_err(ctrl->dev, "async channel not allocated\n"); + return -EINVAL; + } + + handle =3D (struct stratix10_svc_async_handler *)tx_handle; + scoped_guard(spinlock_bh, &actrl->trx_list_lock) { + if (!hash_hashed(&handle->next)) { + dev_err(ctrl->dev, "Invalid transaction handle"); + return -EINVAL; + } + hash_del(&handle->next); + } + ida_free(&achan->job_id_pool, + STRATIX10_GET_JOBID(handle->transaction_id)); + kfree(handle); + return 0; +} +EXPORT_SYMBOL_GPL(stratix10_svc_async_done); + +static inline void stratix10_smc_1_2(struct stratix10_async_ctrl *actrl, + const struct arm_smccc_1_2_regs *args, + struct arm_smccc_1_2_regs *res) +{ + arm_smccc_1_2_smc(args, res); +} + +/** + * stratix10_svc_async_init - Initialize the Stratix10 service + * controller for asynchronous operations. + * @controller: Pointer to the Stratix10 service controller structure. + * + * This function initializes the asynchronous service controller by + * setting up the necessary data structures and initializing the + * transaction list. + * + * Return: 0 on success, -EINVAL if the controller is NULL or already + * initialized, -ENOMEM if memory allocation fails, + * -EADDRINUSE if the client ID is already reserved, or other + * negative error codes on failure. + */ +static int stratix10_svc_async_init(struct stratix10_svc_controller *contr= oller) +{ + struct stratix10_async_ctrl *actrl; + struct arm_smccc_res res; + struct device *dev; + int ret; + + if (!controller) + return -EINVAL; + + actrl =3D &controller->actrl; + + if (actrl->initialized) + return -EINVAL; + + dev =3D controller->dev; + + controller->invoke_fn(INTEL_SIP_SMC_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, &re= s); + if (res.a0 !=3D INTEL_SIP_SMC_STATUS_OK || + !(res.a1 > ASYNC_ATF_MINIMUM_MAJOR_VERSION || + (res.a1 =3D=3D ASYNC_ATF_MINIMUM_MAJOR_VERSION && + res.a2 >=3D ASYNC_ATF_MINIMUM_MINOR_VERSION))) { + dev_err(dev, + "Intel Service Layer Driver: ATF version is not compatible for async op= eration\n"); + return -EINVAL; + } + + actrl->invoke_fn =3D stratix10_smc_1_2; + + ida_init(&actrl->async_id_pool); + + /** + * SIP_SVC_V1_CLIENT_ID is used by V1/stratix10_svc_send() clients + * for communicating with SDM synchronously. We need to restrict + * this in V3/stratix10_svc_async_send() usage to distinguish + * between V1 and V3 messages in El3 firmware. + */ + ret =3D ida_alloc_range(&actrl->async_id_pool, SIP_SVC_V1_CLIENT_ID, + SIP_SVC_V1_CLIENT_ID, GFP_KERNEL); + if (ret < 0) { + dev_err(dev, + "Intel Service Layer Driver: Error on reserving SIP_SVC_V1_CLIENT_ID\n"= ); + ida_destroy(&actrl->async_id_pool); + actrl->invoke_fn =3D NULL; + return -EADDRINUSE; + } + + spin_lock_init(&actrl->trx_list_lock); + hash_init(actrl->trx_list); + atomic_set(&actrl->common_achan_refcount, 0); + + actrl->initialized =3D true; + return 0; +} + +/** + * stratix10_svc_async_exit - Clean up and exit the asynchronous + * service controller + * @ctrl: Pointer to the stratix10_svc_controller structure + * + * This function performs the necessary cleanup for the asynchronous + * service controller. It checks if the controller is valid and if it + * has been initialized. It then locks the transaction list and safely + * removes and deallocates each handler in the list. The function also + * removes any asynchronous clients associated with the controller's + * channels and destroys the asynchronous ID pool. Finally, it resets + * the asynchronous ID pool and invoke function pointers to NULL. + * + * Return: 0 on success, -EINVAL if the controller is invalid or not + * initialized. + */ +static int stratix10_svc_async_exit(struct stratix10_svc_controller *ctrl) +{ + struct stratix10_svc_async_handler *handler; + struct stratix10_async_ctrl *actrl; + struct hlist_node *tmp; + int i; + + if (!ctrl) + return -EINVAL; + + actrl =3D &ctrl->actrl; + + if (!actrl->initialized) + return -EINVAL; + + actrl->initialized =3D false; + + scoped_guard(spinlock_bh, &actrl->trx_list_lock) { + hash_for_each_safe(actrl->trx_list, i, tmp, handler, next) { + ida_free(&handler->achan->job_id_pool, + STRATIX10_GET_JOBID(handler->transaction_id)); + hash_del(&handler->next); + kfree(handler); + } + } + + for (i =3D 0; i < SVC_NUM_CHANNEL; i++) { + if (ctrl->chans[i].async_chan) { + stratix10_svc_remove_async_client(&ctrl->chans[i]); + ctrl->chans[i].async_chan =3D NULL; + } + } + + ida_destroy(&actrl->async_id_pool); + actrl->invoke_fn =3D NULL; + + return 0; +} + /** * stratix10_svc_free_channel() - free service channel * @chan: service channel to be freed @@ -1197,11 +1834,18 @@ static int stratix10_svc_drv_probe(struct platform_= device *pdev) controller->invoke_fn =3D invoke_fn; init_completion(&controller->complete_status); =20 + ret =3D stratix10_svc_async_init(controller); + if (ret) { + dev_dbg(dev, "Intel Service Layer Driver: Error on stratix10_svc_async_i= nit %d\n", + ret); + goto err_destroy_pool; + } + fifo_size =3D sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO; ret =3D kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL); if (ret) { dev_err(dev, "failed to allocate FIFO\n"); - goto err_destroy_pool; + goto err_async_exit; } spin_lock_init(&controller->svc_fifo_lock); =20 @@ -1277,6 +1921,8 @@ static int stratix10_svc_drv_probe(struct platform_de= vice *pdev) platform_device_unregister(svc->stratix10_svc_rsu); err_free_kfifo: kfifo_free(&controller->svc_fifo); +err_async_exit: + stratix10_svc_async_exit(controller); err_destroy_pool: gen_pool_destroy(genpool); return ret; @@ -1287,6 +1933,8 @@ static void stratix10_svc_drv_remove(struct platform_= device *pdev) struct stratix10_svc *svc =3D dev_get_drvdata(&pdev->dev); struct stratix10_svc_controller *ctrl =3D platform_get_drvdata(pdev); =20 + stratix10_svc_async_exit(ctrl); + of_platform_depopulate(ctrl->dev); =20 platform_device_unregister(svc->intel_svc_fcs); diff --git a/include/linux/firmware/intel/stratix10-smc.h b/include/linux/f= irmware/intel/stratix10-smc.h index 7306dd243b2a2ac2fdd91d664fcceb1f506ab7b1..3995d5d70cce029466da8943ebe= a392ee2f19777 100644 --- a/include/linux/firmware/intel/stratix10-smc.h +++ b/include/linux/firmware/intel/stratix10-smc.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2017-2018, Intel Corporation + * Copyright (C) 2025, Altera Corporation */ =20 #ifndef __STRATIX10_SMC_H @@ -47,6 +48,10 @@ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \ ARM_SMCCC_OWNER_SIP, (func_num)) =20 +#define INTEL_SIP_SMC_ASYNC_VAL(func_name) \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_SIP, (func_name)) + /** * Return values in INTEL_SIP_SMC_* call * @@ -654,4 +659,24 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_= CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_HWMON_READVOLT \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HWMON_READVOLT) =20 +/** + * Request INTEL_SIP_SMC_ASYNC_POLL + * Async call used by service driver at EL1 to query mailbox response from= SDM. + * + * Call register usage: + * a0 INTEL_SIP_SMC_ASYNC_POLL + * a1 transaction job id + * a2-17 will be used to return the response data + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + * a1-17 will contain the response values from mailbox for the previous se= nd + * transaction + * Or + * a0 INTEL_SIP_SMC_STATUS_NO_RESPONSE + * a1-17 not used + */ +#define INTEL_SIP_SMC_ASYNC_FUNC_ID_POLL (0xC8) +#define INTEL_SIP_SMC_ASYNC_POLL \ + INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_POLL) #endif diff --git a/include/linux/firmware/intel/stratix10-svc-client.h b/include/= linux/firmware/intel/stratix10-svc-client.h index 520004a5f15dd1900903d65819f6b48e3723e56b..532dd4bd76dd8e2144a2a8e3158= 168ed776b3fa8 100644 --- a/include/linux/firmware/intel/stratix10-svc-client.h +++ b/include/linux/firmware/intel/stratix10-svc-client.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2017-2018, Intel Corporation + * Copyright (C) 2025, Altera Corporation */ =20 #ifndef __STRATIX10_SVC_CLIENT_H @@ -290,5 +291,92 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan= , void *msg); * request process. */ void stratix10_svc_done(struct stratix10_svc_chan *chan); + +/** + * typedef async_callback_t - A type definition for an asynchronous callba= ck function. + * + * This type defines a function pointer for an asynchronous callback. + * The callback function takes a single argument, which is a pointer to + * user-defined data. + * + * @param cb_arg A pointer to user-defined data passed to the callback fun= ction. + */ +typedef void (*async_callback_t)(void *cb_arg); + +/** + * stratix10_svc_add_async_client - Add an asynchronous client to a Strati= x 10 + * service channel. + * @chan: Pointer to the Stratix 10 service channel structure. + * @use_unique_clientid: Boolean flag indicating whether to use a unique c= lient ID. + * + * This function registers an asynchronous client with the specified Strat= ix 10 + * service channel. If the use_unique_clientid flag is set to true, a uniq= ue client + * ID will be assigned to the client. + * + * Return: 0 on success, or a negative error code on failure: + * -EINVAL if the channel is NULL or the async controller is not i= nitialized. + * -EALREADY if the async channel is already allocated. + * -ENOMEM if memory allocation fails. + * Other negative values if ID allocation fails + */ +int stratix10_svc_add_async_client(struct stratix10_svc_chan *chan, bool u= se_unique_clientid); + +/** + * stratix10_svc_remove_async_client - Remove an asynchronous client from = the Stratix 10 + * service channel. + * @chan: Pointer to the Stratix 10 service channel structure. + * + * This function removes an asynchronous client from the specified Stratix= 10 service channel. + * It is typically used to clean up and release resources associated with = the client. + * + * Return: 0 on success, -EINVAL if the channel or asynchronous channel is= invalid. + */ +int stratix10_svc_remove_async_client(struct stratix10_svc_chan *chan); + +/** + * stratix10_svc_async_send - Send an asynchronous message to the SDM mail= box + * in EL3 secure firmware. + * @chan: Pointer to the service channel structure. + * @msg: Pointer to the message to be sent. + * @handler: Pointer to the handler object used by caller to track the tra= nsaction. + * @cb: Callback function to be called upon completion. + * @cb_arg: Argument to be passed to the callback function. + * + * This function sends a message asynchronously to the SDM mailbox in EL3 = secure firmware. + * and registers a callback function to be invoked when the operation comp= letes. + * + * Return: 0 on success,and negative error codes on failure. + */ +int stratix10_svc_async_send(struct stratix10_svc_chan *chan, void *msg, v= oid **handler, + async_callback_t cb, void *cb_arg); + +/** + * stratix10_svc_async_poll - Polls the status of an asynchronous service = request. + * @chan: Pointer to the service channel structure. + * @tx_handle: Handle to the transaction being polled. + * @data: Pointer to the callback data structure to be filled with the res= ult. + * + * This function checks the status of an asynchronous service request + * and fills the provided callback data structure with the result. + * + * Return: 0 on success, -EINVAL if any input parameter is invalid or if t= he + * async controller is not initialized, -EAGAIN if the transaction= is + * still in progress, or other negative error codes on failure. + */ +int stratix10_svc_async_poll(struct stratix10_svc_chan *chan, void *tx_han= dle, + struct stratix10_svc_cb_data *data); + +/** + * stratix10_svc_async_done - Complete an asynchronous transaction + * @chan: Pointer to the service channel structure + * @tx_handle: Pointer to the transaction handle + * + * This function completes an asynchronous transaction by removing the + * transaction from the hash table and deallocating the associated resourc= es. + * + * Return: 0 on success, -EINVAL on invalid input or errors. + */ +int stratix10_svc_async_done(struct stratix10_svc_chan *chan, void *tx_han= dle); + #endif =20 --=20 2.43.7 From nobody Sun Dec 14 06:18:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E3192C21D3; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; cv=none; b=Z3R/zaLawrORpNEpCFt4rw8fuZtcBb4t3DWL+BomLkshhvnCOgKXYCUsmLJqHWTLqn+LOgpjTK5run3qkA1m5ftEXGOde63JxjX5ICorO9K5mWKaKojZUJlEK7gGuZUGF3J/OI0xCntqeSDCFdE5MP+8FW3iWrUniwLIiW13SqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; c=relaxed/simple; bh=D385v2uY3jAv6luWXguCh9NpLhE7kibSbnG7jeLsozg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nBa5iQjvNS9AkCGDzb5hzi1tD4in/Tb/12T26duGmJKe0JbxZUBFwF9aRllyG+P8aly70sPbX4u/tICF5zmQUovTMDVJHR1zXLewv0f/wokhUh3WRm0fOtL6arc7J8eD2aszEJwxCO1+RKeTfEwB3tO6gHuMZAEIUAMfcvO414g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JY1tdvZh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JY1tdvZh" Received: by smtp.kernel.org (Postfix) with ESMTPS id 4852BC19421; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761576957; bh=D385v2uY3jAv6luWXguCh9NpLhE7kibSbnG7jeLsozg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=JY1tdvZhyhTV94Pnj2tdEfqde8BDc00OcUhuSL9tN5WntigVUsjIQAGTpslrHBpwk l7xOSphDiC+COylaK3jKUlSwOI7tnYJaKgjRUpydBha/T+vcq2yUK3lQ6py71otNH5 xC3xPNe2pjFfGKU1Ma1YnZ6Za2vbNsDms6/TZApf/PiUjtpnOpeAVnSS7ScFzjbGHG CrmsTNNpaylaIZk61ib+HQZe/cEbN7LXJzerM3mI4BpJkbSpglASkX66FGfmNoQC3x KPIarpXSkVA0CxqBgjIFLtnawTv/KxP4QJ5j4C41wDTmOiL4Vo5PUv5YDR8qnSL600 aPP/qX9dlwA0w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3600BCCF9EA; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) From: Mahesh Rao via B4 Relay Date: Mon, 27 Oct 2025 22:54:42 +0800 Subject: [PATCH v7 3/4] firmware: stratix10-svc: Add support for RSU commands in asynchronous framework Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251027-sip_svc_upstream-v7-3-6e9ab26d7480@altera.com> References: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> In-Reply-To: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> To: Dinh Nguyen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Mahesh Rao , Richard Gong , Alan Tull , Greg Kroah-Hartman Cc: Matthew Gerlach , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1761576953; l=8313; i=mahesh.rao@altera.com; s=20250107; h=from:subject:message-id; bh=iA9XcG2q+a/TSsO5lZazATVYnuLeYIBDmU/cEvshLSY=; b=4+WeLDIvrs/GggwINQS6AJxf7I2FXLRxzwFOfG388QWCxhEq/wIdjKVrgT15ykPFEqhxtpTMC mLUYg9G+HMgBDOnCSlKVmdcGonio+er1kILb2h8OEAvt6CHa6rOKhn3 X-Developer-Key: i=mahesh.rao@altera.com; a=ed25519; pk=tQiFUzoKxHrQLDtWeEeaeTeJTl/UfclUHWZy1fjSiyg= X-Endpoint-Received: by B4 Relay for mahesh.rao@altera.com/20250107 with auth_id=337 X-Original-From: Mahesh Rao Reply-To: mahesh.rao@altera.com From: Mahesh Rao 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 Reviewed-by: Matthew Gerlach Signed-off-by: Dinh Nguyen --- drivers/firmware/stratix10-svc.c | 72 ++++++++++++++++++= ++++ include/linux/firmware/intel/stratix10-smc.h | 52 ++++++++++++++++ .../linux/firmware/intel/stratix10-svc-client.h | 4 ++ 3 files changed, 128 insertions(+) diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-= svc.c index 14bfa36a58ed38a19de9f54142827a29ced0851d..3acfa067c5dda5a1a2d8848a18e= 0627860395902 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)) =20 +/* 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_ch= an *chan, void *msg, STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(handle->transaction_id); =20 switch (p_msg->command) { + case COMMAND_RSU_GET_SPT_TABLE: + args.a0 =3D INTEL_SIP_SMC_ASYNC_RSU_GET_SPT; + break; + case COMMAND_RSU_STATUS: + args.a0 =3D INTEL_SIP_SMC_ASYNC_RSU_GET_ERROR_STATUS; + break; + case COMMAND_RSU_NOTIFY: + args.a0 =3D INTEL_SIP_SMC_ASYNC_RSU_NOTIFY; + args.a2 =3D p_msg->arg[0]; + break; default: dev_err(ctrl->dev, "Invalid command ,%d\n", p_msg->command); ret =3D -EINVAL; @@ -1326,6 +1342,56 @@ int stratix10_svc_async_send(struct stratix10_svc_ch= an *chan, void *msg, 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 transactio= n. It + * extracts the response data from the SMC response structure and stores i= t in + * the callback data structure. The function also logs the completion of t= he + * 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 =3D + (struct stratix10_svc_client_msg *)handle->msg; + struct stratix10_svc_controller *ctrl =3D chan->ctrl; + + data->status =3D 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 =3D (void *)&handle->res.a2; + data->kaddr2 =3D (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 =3D (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_cha= n *chan, struct stratix10_svc_controller *ctrl; struct stratix10_async_ctrl *actrl; struct stratix10_async_chan *achan; + int ret; =20 if (!chan || !tx_handle || !data) return -EINVAL; @@ -1386,6 +1453,11 @@ int stratix10_svc_async_poll(struct stratix10_svc_ch= an *chan, memset(data, 0, sizeof(*data)); =20 if (handle->res.a0 =3D=3D INTEL_SIP_SMC_STATUS_OK) { + ret =3D 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 =3D=3D INTEL_SIP_SMC_STATUS_BUSY) { dev_dbg(ctrl->dev, "async message is still in progress\n"); diff --git a/include/linux/firmware/intel/stratix10-smc.h b/include/linux/f= irmware/intel/stratix10-smc.h index 3995d5d70cce029466da8943ebea392ee2f19777..935dba3633b5ba2d559eeb05290= 3456b69babd76 100644 --- a/include/linux/firmware/intel/stratix10-smc.h +++ b/include/linux/firmware/intel/stratix10-smc.h @@ -679,4 +679,56 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_= CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_ASYNC_FUNC_ID_POLL (0xC8) #define INTEL_SIP_SMC_ASYNC_POLL \ INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_POLL) + +/** + * Request INTEL_SIP_SMC_ASYNC_RSU_GET_SPT + * Async call to get RSU SPT from SDM. + * Call register usage: + * a0 INTEL_SIP_SMC_ASYNC_RSU_GET_SPT + * a1 transaction job id + * a2-a17 not used + * + * Return status: + * a0 INTEL_SIP_SMC_STATUS_OK ,INTEL_SIP_SMC_STATUS_REJECTED + * or INTEL_SIP_SMC_STATUS_BUSY + * a1-a17 not used + */ +#define INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_GET_SPT (0xEA) +#define INTEL_SIP_SMC_ASYNC_RSU_GET_SPT \ + INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_GET_SPT) + +/** + * Request INTEL_SIP_SMC_ASYNC_RSU_GET_ERROR_STATUS + * Async call to get RSU error status from SDM. + * Call register usage: + * a0 INTEL_SIP_SMC_ASYNC_RSU_GET_ERROR_STATUS + * a1 transaction job id + * a2-a17 not used + * + * Return status: + * a0 INTEL_SIP_SMC_STATUS_OK ,INTEL_SIP_SMC_STATUS_REJECTED + * or INTEL_SIP_SMC_STATUS_BUSY + * a1-a17 not used + */ +#define INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_GET_ERROR_STATUS (0xEB) +#define INTEL_SIP_SMC_ASYNC_RSU_GET_ERROR_STATUS \ + INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_GET_ERROR_STATUS) + +/** + * Request INTEL_SIP_SMC_ASYNC_RSU_NOTIFY + * Async call to send NOTIFY value to SDM. + * Call register usage: + * a0 INTEL_SIP_SMC_ASYNC_RSU_NOTIFY + * a1 transaction job id + * a2 notify value + * a3-a17 not used + * + * Return status: + * a0 INTEL_SIP_SMC_STATUS_OK ,INTEL_SIP_SMC_STATUS_REJECTED + * or INTEL_SIP_SMC_STATUS_BUSY + * a1-a17 not used + */ +#define INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_NOTIFY (0xEC) +#define INTEL_SIP_SMC_ASYNC_RSU_NOTIFY \ + INTEL_SIP_SMC_ASYNC_VAL(INTEL_SIP_SMC_ASYNC_FUNC_ID_RSU_NOTIFY) #endif diff --git a/include/linux/firmware/intel/stratix10-svc-client.h b/include/= linux/firmware/intel/stratix10-svc-client.h index 532dd4bd76dd8e2144a2a8e3158168ed776b3fa8..1bcc56d14080d8950a5af60bb31= 052d3bffa8904 100644 --- a/include/linux/firmware/intel/stratix10-svc-client.h +++ b/include/linux/firmware/intel/stratix10-svc-client.h @@ -128,6 +128,9 @@ struct stratix10_svc_chan; * @COMMAND_RSU_DCMF_STATUS: query firmware for the DCMF status * return status is SVC_STATUS_OK or SVC_STATUS_ERROR * + * @COMMAND_RSU_GET_SPT_TABLE: query firmware for SPT table + * return status is SVC_STATUS_OK or SVC_STATUS_ERROR + * * @COMMAND_FCS_REQUEST_SERVICE: request validation of image from firmware, * return status is SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM * @@ -162,6 +165,7 @@ enum stratix10_svc_command_code { COMMAND_RSU_DCMF_VERSION, COMMAND_RSU_DCMF_STATUS, COMMAND_FIRMWARE_VERSION, + COMMAND_RSU_GET_SPT_TABLE, /* for FCS */ COMMAND_FCS_REQUEST_SERVICE =3D 20, COMMAND_FCS_SEND_CERTIFICATE, --=20 2.43.7 From nobody Sun Dec 14 06:18:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E38E2D0C73; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; cv=none; b=nLhb4IVX3fJk+/LSalIeOMki/QFVNXh5Zkb3UWOF+UgTLzAlOenRePaI27ZzDQa/p5yjYwf4OieLwii4OB99Ez4ylALPcn2J/WusPS4VO2/FWfJm6WXtJMiwbEUzhwKmMZ9E4+j5yD0zfRfT1E7Zgrl6GtFEbtWtETLDmi8M9Rw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761576957; c=relaxed/simple; bh=l1N3w7PvYuOermOAC1sh32p7X7YqDIlrtE47Spr7XsQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Gix87hsSiGVO7GI2w+uoRLaxky+9t2cUbGel10kx6bqeuFrVIz0713bpLjNOvM2NJLNdOuq5bFAZnmwmo/sf88ox3hDgvdtZURLSonEaz+z7b+ncqMQwD2WMuyl76u+2gqK4DgvlXRIHMjjg4na8ZN+2s7VlJ3YcbFpLHpkqr+o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ft9s/nSk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ft9s/nSk" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5781EC116B1; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761576957; bh=l1N3w7PvYuOermOAC1sh32p7X7YqDIlrtE47Spr7XsQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ft9s/nSkO8vJxHu40l/crncvgT+CktpafGKHQqnKPpZpKSs9waQ1L8OoP/V1FT4b4 vy4JO4r+JVx8xuXlUy3lTLLMMOstkuI8ZBHjEqBUiWJlh37Ez6Tbx8pMVWSE6eJ32d QxGhGjZJvgBhagi4iarxZbwVDkvHvErjlBtYrX2v89MIpunm5FlVUi8mCLXX/EMLtt ipdv1lqI8VQ97nnJug6MV5Vnsbs3lmFUX6drZVdMz+UpzGtcMpChbvAwCzWseiHQlT PPgPzO7X+xxwWjgfadAMlrrUAYNFRFVFXbIk0+FK6cM012p/RjEp0u1opdVph3xEtQ Y7+NP/1Ji4Xug== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49FA9CCF9E0; Mon, 27 Oct 2025 14:55:57 +0000 (UTC) From: Mahesh Rao via B4 Relay Date: Mon, 27 Oct 2025 22:54:43 +0800 Subject: [PATCH v7 4/4] firmware: stratix10-rsu: Migrate RSU driver to use stratix10 asynchronous framework. Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251027-sip_svc_upstream-v7-4-6e9ab26d7480@altera.com> References: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> In-Reply-To: <20251027-sip_svc_upstream-v7-0-6e9ab26d7480@altera.com> To: Dinh Nguyen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Mahesh Rao , Richard Gong , Alan Tull , Greg Kroah-Hartman Cc: Matthew Gerlach , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1761576953; l=13384; i=mahesh.rao@altera.com; s=20250107; h=from:subject:message-id; bh=EasTpB3pb/7uVYkP5RQQljasDKgKBokFEn3X5P3uAvE=; b=sy9RkTxHaVvJlvz3uSmEV/Nu+utQDNcw7TBK4ne6Ek4VQEePhXv3aQCSj9mFSkRpp691xbMwj KwD5QBwhfARCT6o/osob94mSydhxZmeZ0fdgFeOsyef2UgxFto9nXET X-Developer-Key: i=mahesh.rao@altera.com; a=ed25519; pk=tQiFUzoKxHrQLDtWeEeaeTeJTl/UfclUHWZy1fjSiyg= X-Endpoint-Received: by B4 Relay for mahesh.rao@altera.com/20250107 with auth_id=337 X-Original-From: Mahesh Rao Reply-To: mahesh.rao@altera.com From: Mahesh Rao * Add support for asynchronous communication to the RSU client channel. * Migrate functions that communicate with the SDM to use the asynchronous framework. Signed-off-by: Mahesh Rao Reviewed-by: Matthew Gerlach Signed-off-by: Dinh Nguyen --- drivers/firmware/stratix10-rsu.c | 272 ++++++++++++++++++++---------------= ---- 1 file changed, 142 insertions(+), 130 deletions(-) diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-= rsu.c index 1ea39a0a76c787c6396300734b636b4b3a0ae04d..53b67b242cf0afa4102340aa099= cef66b642effa 100644 --- a/drivers/firmware/stratix10-rsu.c +++ b/drivers/firmware/stratix10-rsu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2018-2019, Intel Corporation + * Copyright (C) 2025, Altera Corporation */ =20 #include @@ -14,11 +15,9 @@ #include #include #include +#include =20 -#define RSU_STATE_MASK GENMASK_ULL(31, 0) -#define RSU_VERSION_MASK GENMASK_ULL(63, 32) -#define RSU_ERROR_LOCATION_MASK GENMASK_ULL(31, 0) -#define RSU_ERROR_DETAIL_MASK GENMASK_ULL(63, 32) +#define RSU_ERASE_SIZE_MASK GENMASK_ULL(63, 32) #define RSU_DCMF0_MASK GENMASK_ULL(31, 0) #define RSU_DCMF1_MASK GENMASK_ULL(63, 32) #define RSU_DCMF2_MASK GENMASK_ULL(31, 0) @@ -35,7 +34,8 @@ #define INVALID_DCMF_STATUS 0xFFFFFFFF #define INVALID_SPT_ADDRESS 0x0 =20 -#define RSU_GET_SPT_CMD 0x5A +#define RSU_RETRY_SLEEP_MS (1U) +#define RSU_ASYNC_MSG_RETRY (3U) #define RSU_GET_SPT_RESP_LEN (4 * sizeof(unsigned int)) =20 typedef void (*rsu_callback)(struct stratix10_svc_client *client, @@ -64,7 +64,6 @@ typedef void (*rsu_callback)(struct stratix10_svc_client = *client, * @max_retry: the preset max retry value * @spt0_address: address of spt0 * @spt1_address: address of spt1 - * @get_spt_response_buf: response from sdm for get_spt command */ struct stratix10_rsu_priv { struct stratix10_svc_chan *chan; @@ -99,47 +98,32 @@ struct stratix10_rsu_priv { =20 unsigned long spt0_address; unsigned long spt1_address; - - unsigned int *get_spt_response_buf; }; =20 +typedef void (*rsu_async_callback)(struct device *dev, + struct stratix10_rsu_priv *priv, struct stratix10_svc_cb_data *data); + /** - * rsu_status_callback() - Status callback from Intel Service Layer - * @client: pointer to service client + * rsu_async_status_callback() - Status callback from rsu_async_send() + * @dev: pointer to device object + * @priv: pointer to priv object * @data: pointer to callback data structure * - * Callback from Intel service layer for RSU status request. Status is - * only updated after a system reboot, so a get updated status call is - * made during driver probe. + * Callback from rsu_async_send() to get the system rsu error status. */ -static void rsu_status_callback(struct stratix10_svc_client *client, - struct stratix10_svc_cb_data *data) +static void rsu_async_status_callback(struct device *dev, + struct stratix10_rsu_priv *priv, + struct stratix10_svc_cb_data *data) { - struct stratix10_rsu_priv *priv =3D client->priv; - struct arm_smccc_res *res =3D (struct arm_smccc_res *)data->kaddr1; - - if (data->status =3D=3D BIT(SVC_STATUS_OK)) { - priv->status.version =3D FIELD_GET(RSU_VERSION_MASK, - res->a2); - priv->status.state =3D FIELD_GET(RSU_STATE_MASK, res->a2); - priv->status.fail_image =3D res->a1; - priv->status.current_image =3D res->a0; - priv->status.error_location =3D - FIELD_GET(RSU_ERROR_LOCATION_MASK, res->a3); - priv->status.error_details =3D - FIELD_GET(RSU_ERROR_DETAIL_MASK, res->a3); - } else { - dev_err(client->dev, "COMMAND_RSU_STATUS returned 0x%lX\n", - res->a0); - priv->status.version =3D 0; - priv->status.state =3D 0; - priv->status.fail_image =3D 0; - priv->status.current_image =3D 0; - priv->status.error_location =3D 0; - priv->status.error_details =3D 0; - } - - complete(&priv->completion); + struct arm_smccc_1_2_regs *res =3D (struct arm_smccc_1_2_regs *)data->kad= dr1; + + priv->status.current_image =3D res->a2; + priv->status.fail_image =3D res->a3; + priv->status.state =3D res->a4; + priv->status.version =3D res->a5; + priv->status.error_location =3D res->a7; + priv->status.error_details =3D res->a8; + priv->retry_counter =3D res->a9; } =20 /** @@ -163,32 +147,6 @@ static void rsu_command_callback(struct stratix10_svc_= client *client, complete(&priv->completion); } =20 -/** - * rsu_retry_callback() - Callback from Intel service layer for getting - * the current image's retry counter from the firmware - * @client: pointer to client - * @data: pointer to callback data structure - * - * Callback from Intel service layer for retry counter, which is used by - * user to know how many times the images is still allowed to reload - * itself before giving up and starting RSU fail-over flow. - */ -static void rsu_retry_callback(struct stratix10_svc_client *client, - struct stratix10_svc_cb_data *data) -{ - struct stratix10_rsu_priv *priv =3D client->priv; - unsigned int *counter =3D (unsigned int *)data->kaddr1; - - if (data->status =3D=3D BIT(SVC_STATUS_OK)) - priv->retry_counter =3D *counter; - else if (data->status =3D=3D BIT(SVC_STATUS_NO_SUPPORT)) - dev_warn(client->dev, "Secure FW doesn't support retry\n"); - else - dev_err(client->dev, "Failed to get retry counter %lu\n", - BIT(data->status)); - - complete(&priv->completion); -} =20 /** * rsu_max_retry_callback() - Callback from Intel service layer for getting @@ -270,34 +228,19 @@ static void rsu_dcmf_status_callback(struct stratix10= _svc_client *client, complete(&priv->completion); } =20 -static void rsu_get_spt_callback(struct stratix10_svc_client *client, - struct stratix10_svc_cb_data *data) +/** + * rsu_async_get_spt_table_callback() - Callback to be used by the rsu_asy= nc_send() + * to retrieve the SPT table information. + * @dev: pointer to device object + * @priv: pointer to priv object + * @data: pointer to callback data structure + */ +static void rsu_async_get_spt_table_callback(struct device *dev, + struct stratix10_rsu_priv *priv, + struct stratix10_svc_cb_data *data) { - struct stratix10_rsu_priv *priv =3D client->priv; - unsigned long *mbox_err =3D (unsigned long *)data->kaddr1; - unsigned long *resp_len =3D (unsigned long *)data->kaddr2; - - if (data->status !=3D BIT(SVC_STATUS_OK) || (*mbox_err) || - (*resp_len !=3D RSU_GET_SPT_RESP_LEN)) - goto error; - - priv->spt0_address =3D priv->get_spt_response_buf[0]; - priv->spt0_address <<=3D 32; - priv->spt0_address |=3D priv->get_spt_response_buf[1]; - - priv->spt1_address =3D priv->get_spt_response_buf[2]; - priv->spt1_address <<=3D 32; - priv->spt1_address |=3D priv->get_spt_response_buf[3]; - - goto complete; - -error: - dev_err(client->dev, "failed to get SPTs\n"); - -complete: - stratix10_svc_free_memory(priv->chan, priv->get_spt_response_buf); - priv->get_spt_response_buf =3D NULL; - complete(&priv->completion); + priv->spt0_address =3D *((unsigned long *)data->kaddr1); + priv->spt1_address =3D *((unsigned long *)data->kaddr2); } =20 /** @@ -329,14 +272,6 @@ static int rsu_send_msg(struct stratix10_rsu_priv *pri= v, if (arg) msg.arg[0] =3D arg; =20 - if (command =3D=3D COMMAND_MBOX_SEND_CMD) { - msg.arg[1] =3D 0; - msg.payload =3D NULL; - msg.payload_length =3D 0; - msg.payload_output =3D priv->get_spt_response_buf; - msg.payload_length_output =3D RSU_GET_SPT_RESP_LEN; - } - ret =3D stratix10_svc_send(priv->chan, &msg); if (ret < 0) goto status_done; @@ -362,6 +297,95 @@ static int rsu_send_msg(struct stratix10_rsu_priv *pri= v, return ret; } =20 +/** + * soc64_async_callback() - Callback from Intel service layer for async re= quests + * @ptr: pointer to the completion object + */ +static void soc64_async_callback(void *ptr) +{ + if (ptr) + complete(ptr); +} + +/** + * rsu_send_async_msg() - send an async message to Intel service layer + * @dev: pointer to device object + * @priv: pointer to rsu private data + * @command: RSU status or update command + * @arg: the request argument, notify status + * @callback: function pointer for the callback (status or update) + */ +static int rsu_send_async_msg(struct device *dev, struct stratix10_rsu_pri= v *priv, + enum stratix10_svc_command_code command, + unsigned long arg, + rsu_async_callback callback) +{ + struct stratix10_svc_client_msg msg =3D {0}; + struct stratix10_svc_cb_data data =3D {0}; + struct completion completion; + int status, index, ret; + void *handle =3D NULL; + + msg.command =3D command; + msg.arg[0] =3D arg; + + init_completion(&completion); + + for (index =3D 0; index < RSU_ASYNC_MSG_RETRY; index++) { + status =3D stratix10_svc_async_send(priv->chan, &msg, + &handle, soc64_async_callback, + &completion); + if (status =3D=3D 0) + break; + dev_warn(dev, "Failed to send async message\n"); + msleep(RSU_RETRY_SLEEP_MS); + } + + if (status && !handle) { + dev_err(dev, "Failed to send async message\n"); + return -ETIMEDOUT; + } + + ret =3D wait_for_completion_io_timeout(&completion, RSU_TIMEOUT); + if (ret > 0) + dev_dbg(dev, "Received async interrupt\n"); + else if (ret =3D=3D 0) + dev_dbg(dev, "Timeout occurred. Trying to poll the response\n"); + + for (index =3D 0; index < RSU_ASYNC_MSG_RETRY; index++) { + status =3D stratix10_svc_async_poll(priv->chan, handle, &data); + if (status =3D=3D -EAGAIN) { + dev_dbg(dev, "Async message is still in progress\n"); + } else if (status < 0) { + dev_alert(dev, "Failed to poll async message\n"); + ret =3D -ETIMEDOUT; + } else if (status =3D=3D 0) { + ret =3D 0; + break; + } + msleep(RSU_RETRY_SLEEP_MS); + } + + if (ret) { + dev_err(dev, "Failed to get async response\n"); + goto status_done; + } + + if (data.status =3D=3D 0) { + ret =3D 0; + if (callback) + callback(dev, priv, &data); + } else { + dev_err(dev, "%s returned 0x%x from SDM\n", __func__, + data.status); + ret =3D -EFAULT; + } + +status_done: + stratix10_svc_async_done(priv->chan, handle); + return ret; +} + /* * This driver exposes some optional features of the Intel Stratix 10 SoC = FPGA. * The sysfs interfaces exposed here are FPGA Remote System Update (RSU) @@ -597,27 +621,20 @@ static ssize_t notify_store(struct device *dev, if (ret) return ret; =20 - ret =3D rsu_send_msg(priv, COMMAND_RSU_NOTIFY, - status, rsu_command_callback); + ret =3D rsu_send_async_msg(dev, priv, COMMAND_RSU_NOTIFY, status, NULL); if (ret) { dev_err(dev, "Error, RSU notify returned %i\n", ret); return ret; } =20 /* to get the updated state */ - ret =3D rsu_send_msg(priv, COMMAND_RSU_STATUS, - 0, rsu_status_callback); + ret =3D rsu_send_async_msg(dev, priv, COMMAND_RSU_STATUS, 0, + rsu_async_status_callback); if (ret) { dev_err(dev, "Error, getting RSU status %i\n", ret); return ret; } =20 - ret =3D rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); - if (ret) { - dev_err(dev, "Error, getting RSU retry %i\n", ret); - return ret; - } - return count; } =20 @@ -737,12 +754,19 @@ static int stratix10_rsu_probe(struct platform_device= *pdev) return PTR_ERR(priv->chan); } =20 + ret =3D stratix10_svc_add_async_client(priv->chan, false); + if (ret) { + dev_err(dev, "failed to add async client\n"); + stratix10_svc_free_channel(priv->chan); + return ret; + } + init_completion(&priv->completion); platform_set_drvdata(pdev, priv); =20 /* get the initial state from firmware */ - ret =3D rsu_send_msg(priv, COMMAND_RSU_STATUS, - 0, rsu_status_callback); + ret =3D rsu_send_async_msg(dev, priv, COMMAND_RSU_STATUS, 0, + rsu_async_status_callback); if (ret) { dev_err(dev, "Error, getting RSU status %i\n", ret); stratix10_svc_free_channel(priv->chan); @@ -763,12 +787,6 @@ static int stratix10_rsu_probe(struct platform_device = *pdev) stratix10_svc_free_channel(priv->chan); } =20 - ret =3D rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); - if (ret) { - dev_err(dev, "Error, getting RSU retry %i\n", ret); - stratix10_svc_free_channel(priv->chan); - } - ret =3D rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0, rsu_max_retry_callback); if (ret) { @@ -776,18 +794,12 @@ static int stratix10_rsu_probe(struct platform_device= *pdev) stratix10_svc_free_channel(priv->chan); } =20 - priv->get_spt_response_buf =3D - stratix10_svc_allocate_memory(priv->chan, RSU_GET_SPT_RESP_LEN); =20 - if (IS_ERR(priv->get_spt_response_buf)) { - dev_err(dev, "failed to allocate get spt buffer\n"); - } else { - ret =3D rsu_send_msg(priv, COMMAND_MBOX_SEND_CMD, - RSU_GET_SPT_CMD, rsu_get_spt_callback); - if (ret) { - dev_err(dev, "Error, getting SPT table %i\n", ret); - stratix10_svc_free_channel(priv->chan); - } + ret =3D rsu_send_async_msg(dev, priv, COMMAND_RSU_GET_SPT_TABLE, 0, + rsu_async_get_spt_table_callback); + if (ret) { + dev_err(dev, "Error, getting SPT table %i\n", ret); + stratix10_svc_free_channel(priv->chan); } =20 return ret; --=20 2.43.7