[PATCH v4 2/2] firmware: arm_scmi: Augment SMC/HVC to allow optional parameters

Nikunj Kela quic_nkela at quicinc.com
Tue May 2 07:41:01 PDT 2023


On 5/2/2023 3:46 AM, Sudeep Holla wrote:
> On Mon, May 01, 2023 at 07:39:29AM -0700, Nikunj Kela wrote:
>> Reminder: Please review this patch! Thanks
>>
> Since the current merge window is open, there is no rush and hence I had put
> this on hold until merge window close. Anyways, it looks good in general.
> Couple of minor nits below:
Sure, thanks!
>> On 4/18/2023 11:56 AM, Nikunj Kela wrote:
>>> This patch add support for passing shmem channel address as parameters
>>> in smc/hvc call. The address is split into 4KB-page and offset.
>>> This patch is useful when multiple scmi instances are using same smc-id
>>> and firmware needs to distinguish among the instances.
>>>
> Drop the term "patch". You can refer it as change. It is not match after
> it is applied to the git.
ACK!
>>> Signed-off-by: Nikunj Kela <quic_nkela at quicinc.com>
>>> ---
>>>    drivers/firmware/arm_scmi/driver.c |  1 +
>>>    drivers/firmware/arm_scmi/smc.c    | 14 +++++++++++++-
>>>    2 files changed, 14 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
>>> index e7d97b59963b..b5957cc12fee 100644
>>> --- a/drivers/firmware/arm_scmi/driver.c
>>> +++ b/drivers/firmware/arm_scmi/driver.c
>>> @@ -2914,6 +2914,7 @@ static const struct of_device_id scmi_of_match[] = {
>>>    #endif
>>>    #ifdef CONFIG_ARM_SCMI_TRANSPORT_SMC
>>>    	{ .compatible = "arm,scmi-smc", .data = &scmi_smc_desc},
>>> +	{ .compatible = "arm,scmi-smc-param", .data = &scmi_smc_desc},
>>>    #endif
>>>    #ifdef CONFIG_ARM_SCMI_TRANSPORT_VIRTIO
>>>    	{ .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc},
>>> diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
>>> index 93272e4bbd12..71e080b70df5 100644
>>> --- a/drivers/firmware/arm_scmi/smc.c
>>> +++ b/drivers/firmware/arm_scmi/smc.c
>>> @@ -20,6 +20,11 @@
>>>    #include "common.h"
>>> +#define SHMEM_SHIFT 12
>>> +#define SHMEM_SIZE (_AC(1, UL) << SHMEM_SHIFT)
>>> +#define SHMEM_PAGE(x) ((unsigned long)((x) >> SHMEM_SHIFT))
> Since we are dealing with 4kB pages only, I prefer to do:
> #define SHMEM_SIZE     (SZ_4K)
> #define SHMEM_SHIFT    12
> #define SHMEM_PAGE(x) (_UL((x) >> SHMEM_SHIFT))
ACK!
>>> +#define SHMEM_OFFSET(x) ((x) & (SHMEM_SIZE - 1))
>>> +
> Also it is definitely worth adding comment about supporting just 4kB pages
> and limitations associated with it here(e.g. we can support up to 44 bit
> address) and also parameters to the SMC call so that others get clear
> idea on how to use it if they need that in the future.
ACK!
>>>    /**
>>>     * struct scmi_smc - Structure representing a SCMI smc transport
>>>     *
>>> @@ -30,6 +35,7 @@
>>>     * @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
>>>     *	      Used when operating in atomic mode.
>>>     * @func_id: smc/hvc call function id
>>> + * @param: physical address of the shmem channel
>>>     */
>>>    struct scmi_smc {
>>> @@ -40,6 +46,7 @@ struct scmi_smc {
>>>    #define INFLIGHT_NONE	MSG_TOKEN_MAX
>>>    	atomic_t inflight;
>>>    	u32 func_id;
>>> +	phys_addr_t param;
>>>    };
>>>    static irqreturn_t smc_msg_done_isr(int irq, void *data)
>>> @@ -137,6 +144,8 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
>>>    	if (ret < 0)
>>>    		return ret;
>>> +	if (of_device_is_compatible(dev->of_node, "arm,scmi-smc-param"))
>>> +		scmi_info->param = res.start;
>>>    	/*
>>>    	 * If there is an interrupt named "a2p", then the service and
>>>    	 * completion of a message is signaled by an interrupt rather than by
>>> @@ -179,6 +188,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
>>>    {
>>>    	struct scmi_smc *scmi_info = cinfo->transport_info;
>>>    	struct arm_smccc_res res;
>>> +	unsigned long page = SHMEM_PAGE(scmi_info->param);
>>> +	unsigned long offset = SHMEM_OFFSET(scmi_info->param);
> While I see you initialise param in smc_chan_setup, I wonder why the page
> and offset itself be initialised once and reused instead of computing the
> same fixed value on every smc_send_message. You can probably have param_page
> and param_offset stashed instead of just single param value ?
Yeah, I did think of that but then I dropped it since in the earlier 
versions of patches when I was using a flag to identify smc32/smc64 
convention used, I was told to not include it in the scmi_info struct, 
instead compute using local variable. Anyway, I will use the two values 
as advised!
>>>    	/*
>>>    	 * Channel will be released only once response has been
>>> @@ -188,7 +199,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
>>>    	shmem_tx_prepare(scmi_info->shmem, xfer, cinfo);
>>> -	arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res);
>>> +	arm_smccc_1_1_invoke(scmi_info->func_id, page, offset, 0, 0, 0, 0, 0,
>>> +			     &res);
>>>    	/* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
>>>    	if (res.a0) {



More information about the linux-arm-kernel mailing list