From: Cristian Marussi <cristian.marussi@arm.com>
To: Florian Fainelli <florian.fainelli@broadcom.com>
Cc: linux-kernel@vger.kernel.org, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Sudeep Holla <sudeep.holla@arm.com>,
Cristian Marussi <cristian.marussi@arm.com>,
"open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS"
<devicetree@vger.kernel.org>,
"open list:SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE"
<arm-scmi@vger.kernel.org>,
"moderated list:SYSTEM CONTROL & POWER/MANAGEMENT INTERFACE"
<linux-arm-kernel@lists.infradead.org>,
justin.chen@broadcom.com, opendmb@gmail.com,
kapil.hali@broadcom.com, bcm-kernel-feedback-list@broadcom.com
Subject: Re: [PATCH v2 2/2] firmware: arm_scmi: Support 'reg-io-width' property for shared memory
Date: Fri, 16 Aug 2024 18:02:30 +0100 [thread overview]
Message-ID: <Zr-GJts3Gu6GEkhC@pluto> (raw)
In-Reply-To: <20240813180747.1439034-3-florian.fainelli@broadcom.com>
On Tue, Aug 13, 2024 at 11:07:47AM -0700, Florian Fainelli wrote:
> Some shared memory areas might only support a certain access width,
> such as 32-bit, which memcpy_{from,to}_io() does not adhere to at least
> on ARM64 by making both 8-bit and 64-bit accesses to such memory.
>
> Update the shmem layer to support reading from and writing to such
> shared memory area using the specified I/O width in the Device Tree. The
> various transport layers making use of the shmem.c code are updated
> accordingly to pass the I/O accessors that they store.
>
Hi Florian,
I gave it ago at this on a JUNO regarding the mailbox/shmem transport
without any issue. I'll have a go later on an OPTEE/shmem scenario too.
This looks fundamentally good to me, since you moved all ops setup at
setup time and you keep the pointers per-channel instead of global...
A few remarks down below.
> Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
> ---
> drivers/firmware/arm_scmi/common.h | 32 +++++++-
> .../arm_scmi/scmi_transport_mailbox.c | 13 ++-
> .../firmware/arm_scmi/scmi_transport_optee.c | 10 ++-
> .../firmware/arm_scmi/scmi_transport_smc.c | 11 ++-
> drivers/firmware/arm_scmi/shmem.c | 81 +++++++++++++++++--
> 5 files changed, 126 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
> index 69928bbd01c2..73bb496fac01 100644
> --- a/drivers/firmware/arm_scmi/common.h
> +++ b/drivers/firmware/arm_scmi/common.h
> @@ -316,6 +316,26 @@ enum scmi_bad_msg {
> MSG_MBOX_SPURIOUS = -5,
> };
>
> +/* Used for compactness and signature validation of the function pointers being
> + * passed.
> + */
> +typedef void (*shmem_copy_toio_t)(volatile void __iomem *to, const void *from,
> + size_t count);
> +typedef void (*shmem_copy_fromio_t)(void *to, const volatile void __iomem *from,
> + size_t count);
> +
> +/**
> + * struct scmi_shmem_io_ops - I/O operations to read from/write to
> + * Shared Memory
> + *
> + * @toio: Copy data to the shared memory area
> + * @fromio: Copy data from the shared memory area
> + */
> +struct scmi_shmem_io_ops {
> + shmem_copy_fromio_t fromio;
> + shmem_copy_toio_t toio;
> +};
> +
> /* shmem related declarations */
> struct scmi_shared_mem;
>
> @@ -336,13 +356,16 @@ struct scmi_shared_mem;
> struct scmi_shared_mem_operations {
> void (*tx_prepare)(struct scmi_shared_mem __iomem *shmem,
> struct scmi_xfer *xfer,
> - struct scmi_chan_info *cinfo);
> + struct scmi_chan_info *cinfo,
> + shmem_copy_toio_t toio);
> u32 (*read_header)(struct scmi_shared_mem __iomem *shmem);
>
> void (*fetch_response)(struct scmi_shared_mem __iomem *shmem,
> - struct scmi_xfer *xfer);
> + struct scmi_xfer *xfer,
> + shmem_copy_fromio_t fromio);
> void (*fetch_notification)(struct scmi_shared_mem __iomem *shmem,
> - size_t max_len, struct scmi_xfer *xfer);
> + size_t max_len, struct scmi_xfer *xfer,
> + shmem_copy_fromio_t fromio);
> void (*clear_channel)(struct scmi_shared_mem __iomem *shmem);
> bool (*poll_done)(struct scmi_shared_mem __iomem *shmem,
> struct scmi_xfer *xfer);
> @@ -350,7 +373,8 @@ struct scmi_shared_mem_operations {
> bool (*channel_intr_enabled)(struct scmi_shared_mem __iomem *shmem);
> void __iomem *(*setup_iomap)(struct scmi_chan_info *cinfo,
> struct device *dev,
> - bool tx, struct resource *res);
> + bool tx, struct resource *res,
> + struct scmi_shmem_io_ops **ops);
> };
>
> const struct scmi_shared_mem_operations *scmi_shared_mem_operations_get(void);
> diff --git a/drivers/firmware/arm_scmi/scmi_transport_mailbox.c b/drivers/firmware/arm_scmi/scmi_transport_mailbox.c
> index dc5ca894d5eb..2a624870954d 100644
> --- a/drivers/firmware/arm_scmi/scmi_transport_mailbox.c
> +++ b/drivers/firmware/arm_scmi/scmi_transport_mailbox.c
> @@ -25,6 +25,7 @@
> * @chan_platform_receiver: Optional Platform Receiver mailbox unidirectional channel
> * @cinfo: SCMI channel info
> * @shmem: Transmit/Receive shared memory area
> + * @shmem_io_ops: Transport specific I/O operations
Fix the doxy param name...it s op_ops now.
> */
> struct scmi_mailbox {
> struct mbox_client cl;
> @@ -33,6 +34,7 @@ struct scmi_mailbox {
> struct mbox_chan *chan_platform_receiver;
> struct scmi_chan_info *cinfo;
> struct scmi_shared_mem __iomem *shmem;
> + struct scmi_shmem_io_ops *io_ops;
> };
>
> #define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl)
> @@ -43,7 +45,8 @@ static void tx_prepare(struct mbox_client *cl, void *m)
> {
> struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
>
> - core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo);
> + core->shmem->tx_prepare(smbox->shmem, m, smbox->cinfo,
> + smbox->io_ops->toio);
> }
>
> static void rx_callback(struct mbox_client *cl, void *m)
> @@ -197,7 +200,8 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
> if (!smbox)
> return -ENOMEM;
>
> - smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL);
> + smbox->shmem = core->shmem->setup_iomap(cinfo, dev, tx, NULL,
> + &smbox->io_ops);
> if (IS_ERR(smbox->shmem))
> return PTR_ERR(smbox->shmem);
>
> @@ -298,7 +302,7 @@ static void mailbox_fetch_response(struct scmi_chan_info *cinfo,
> {
> struct scmi_mailbox *smbox = cinfo->transport_info;
>
> - core->shmem->fetch_response(smbox->shmem, xfer);
> + core->shmem->fetch_response(smbox->shmem, xfer, smbox->io_ops->fromio);
> }
>
> static void mailbox_fetch_notification(struct scmi_chan_info *cinfo,
> @@ -306,7 +310,8 @@ static void mailbox_fetch_notification(struct scmi_chan_info *cinfo,
> {
> struct scmi_mailbox *smbox = cinfo->transport_info;
>
> - core->shmem->fetch_notification(smbox->shmem, max_len, xfer);
> + core->shmem->fetch_notification(smbox->shmem, max_len, xfer,
> + smbox->io_ops->fromio);
> }
>
> static void mailbox_clear_channel(struct scmi_chan_info *cinfo)
> diff --git a/drivers/firmware/arm_scmi/scmi_transport_optee.c b/drivers/firmware/arm_scmi/scmi_transport_optee.c
> index 08911f40d1ff..fba312128426 100644
> --- a/drivers/firmware/arm_scmi/scmi_transport_optee.c
> +++ b/drivers/firmware/arm_scmi/scmi_transport_optee.c
> @@ -128,6 +128,7 @@ struct scmi_optee_channel {
> struct scmi_shared_mem __iomem *shmem;
> struct scmi_msg_payld *msg;
> } req;
> + struct scmi_shmem_io_ops *io_ops;
Describe this in the doxy....
> struct tee_shm *tee_shm;
> struct list_head link;
> };
> @@ -350,7 +351,8 @@ static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *ch
> static int setup_static_shmem(struct device *dev, struct scmi_chan_info *cinfo,
> struct scmi_optee_channel *channel)
> {
> - channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL);
> + channel->req.shmem = core->shmem->setup_iomap(cinfo, dev, true, NULL,
> + &channel->io_ops);
> if (IS_ERR(channel->req.shmem))
> return PTR_ERR(channel->req.shmem);
>
> @@ -465,7 +467,8 @@ static int scmi_optee_send_message(struct scmi_chan_info *cinfo,
> ret = invoke_process_msg_channel(channel,
> core->msg->command_size(xfer));
> } else {
> - core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo);
> + core->shmem->tx_prepare(channel->req.shmem, xfer, cinfo,
> + channel->io_ops->toio);
> ret = invoke_process_smt_channel(channel);
> }
>
> @@ -484,7 +487,8 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
> core->msg->fetch_response(channel->req.msg,
> channel->rx_len, xfer);
> else
> - core->shmem->fetch_response(channel->req.shmem, xfer);
> + core->shmem->fetch_response(channel->req.shmem, xfer,
> + channel->io_ops->fromio);
> }
>
> static void scmi_optee_mark_txdone(struct scmi_chan_info *cinfo, int ret,
> diff --git a/drivers/firmware/arm_scmi/scmi_transport_smc.c b/drivers/firmware/arm_scmi/scmi_transport_smc.c
> index c6c69a17a9cc..1de06c2fc63a 100644
> --- a/drivers/firmware/arm_scmi/scmi_transport_smc.c
> +++ b/drivers/firmware/arm_scmi/scmi_transport_smc.c
> @@ -45,6 +45,7 @@
> * @irq: An optional IRQ for completion
> * @cinfo: SCMI channel info
> * @shmem: Transmit/Receive shared memory area
> + * @shmem_io_ops: Transport specific I/O operations
Fix doxy param name
> * @shmem_lock: Lock to protect access to Tx/Rx shared memory area.
> * Used when NOT operating in atomic mode.
> * @inflight: Atomic flag to protect access to Tx/Rx shared memory area.
> @@ -60,6 +61,7 @@ struct scmi_smc {
> int irq;
> struct scmi_chan_info *cinfo;
> struct scmi_shared_mem __iomem *shmem;
> + struct scmi_shmem_io_ops *io_ops;
> /* Protect access to shmem area */
> struct mutex shmem_lock;
> #define INFLIGHT_NONE MSG_TOKEN_MAX
> @@ -144,7 +146,8 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
> if (!scmi_info)
> return -ENOMEM;
>
> - scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res);
> + scmi_info->shmem = core->shmem->setup_iomap(cinfo, dev, tx, &res,
> + &scmi_info->io_ops);
> if (IS_ERR(scmi_info->shmem))
> return PTR_ERR(scmi_info->shmem);
>
> @@ -229,7 +232,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo,
> */
> smc_channel_lock_acquire(scmi_info, xfer);
>
> - core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo);
> + core->shmem->tx_prepare(scmi_info->shmem, xfer, cinfo,
> + scmi_info->io_ops->toio);
>
> if (scmi_info->cap_id != ULONG_MAX)
> arm_smccc_1_1_invoke(scmi_info->func_id, scmi_info->cap_id, 0,
> @@ -253,7 +257,8 @@ static void smc_fetch_response(struct scmi_chan_info *cinfo,
> {
> struct scmi_smc *scmi_info = cinfo->transport_info;
>
> - core->shmem->fetch_response(scmi_info->shmem, xfer);
> + core->shmem->fetch_response(scmi_info->shmem, xfer,
> + scmi_info->io_ops->fromio);
> }
>
> static void smc_mark_txdone(struct scmi_chan_info *cinfo, int ret,
> diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c
> index 01d8a9398fe8..139bbbc4b2ee 100644
> --- a/drivers/firmware/arm_scmi/shmem.c
> +++ b/drivers/firmware/arm_scmi/shmem.c
> @@ -34,9 +34,62 @@ struct scmi_shared_mem {
> u8 msg_payload[];
> };
>
> +#define SHMEM_IO_OPS(w, s, amt) \
> +static inline void shmem_memcpy_fromio##s(void *to, \
> + const volatile void __iomem *from, \
> + size_t count) \
> +{ \
> + while (count) { \
> + *(u##s *)to = __raw_read##w(from); \
> + from += amt; \
> + to += amt; \
> + count -= amt; \
> + } \
> +}
... I may be missing a lot here...bear with me...so...
... AFAIU, as suggested by Peng, you moved away from iowrite##s and ioread##s
in favour of __raw_write/read##w so as to avoid the implicit barriers on each
loop iteration...(I suppose..)
...but should we place some sort of final io barrier (similarly to iowrite)
at the end of the loop ?
> +static inline void shmem_memcpy_toio##s(volatile void __iomem *to, \
> + const void *from, \
> + size_t count) \
> +{ \
> + while (count) { \
> + __raw_write##w(*(u##s *)from, to); \
> + from += amt; \
> + to += amt; \
> + count -= amt; \
> + } \
> +}
...same concern here
> +static struct scmi_shmem_io_ops shmem_io_ops##s = { \
> + .fromio = shmem_memcpy_fromio##s, \
> + .toio = shmem_memcpy_toio##s, \
> +};
> +
There are a bunch of warn/errs from checkpatch --strict, beside the volatile
here and on the previous typedefs, also about args reuse and trailing semicolon
in these macros...
Thanks,
Cristian
next prev parent reply other threads:[~2024-08-16 17:02 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-13 18:07 [PATCH v2 0/2] Support for I/O width within ARM SCMI SHMEM Florian Fainelli
2024-08-13 18:07 ` [PATCH v2 1/2] dt-bindings: sram: Document reg-io-width property Florian Fainelli
2024-08-13 19:29 ` Rob Herring (Arm)
2024-08-13 20:08 ` Florian Fainelli
2024-08-13 18:07 ` [PATCH v2 2/2] firmware: arm_scmi: Support 'reg-io-width' property for shared memory Florian Fainelli
2024-08-16 17:02 ` Cristian Marussi [this message]
2024-08-16 17:39 ` Florian Fainelli
2024-08-16 17:54 ` Cristian Marussi
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=Zr-GJts3Gu6GEkhC@pluto \
--to=cristian.marussi@arm.com \
--cc=arm-scmi@vger.kernel.org \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=florian.fainelli@broadcom.com \
--cc=justin.chen@broadcom.com \
--cc=kapil.hali@broadcom.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=opendmb@gmail.com \
--cc=robh@kernel.org \
--cc=sudeep.holla@arm.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.