diff options
author | Etienne Carriere <etienne.carriere@linaro.org> | 2022-05-31 18:09:16 +0200 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-06-23 13:12:55 -0400 |
commit | 593eac9805de7c0c5744da9c1a86d736c083d8b9 (patch) | |
tree | ce2c67613d9d7dd3a5f66c7515a1c45c92f1e955 /drivers/firmware/scmi/smt.c | |
parent | 9121478ee6f2aee381f8fe49d8997d43527d351a (diff) |
firmware: scmi: optee: use TEE shared memory for SCMI messages
Changes implementation when using TEE dynamically allocated shared
memory to synchronize with the Linux implementation where the legacy
SMT protocol cannot be used with such memory since it is expected from
device mapped memory whereas OP-TEE shared memory is cached and
hence should not be accessed using memcpy_toio()/memcpy_fromio().
This change implements the MSG shared memory protocol introduced
in Linux [1]. The protocol uses a simplified SMT header of 32bit
named MSG_SMT to carry SCMI protocol information and uses side channel
means to carry exchanged buffer size information, as TEE invocation API
parameters when used in the SCMI OP-TEE transport.
Link: [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f301bba0ca7392d16a6ea4f1d264a91f1fadea1a
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
Diffstat (limited to 'drivers/firmware/scmi/smt.c')
-rw-r--r-- | drivers/firmware/scmi/smt.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c index e60c2aebc89..509ed618a99 100644 --- a/drivers/firmware/scmi/smt.c +++ b/drivers/firmware/scmi/smt.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. - * Copyright (C) 2019-2020 Linaro Limited. + * Copyright (C) 2019-2022 Linaro Limited. */ #define LOG_CATEGORY UCLASS_SCMI_AGENT @@ -137,3 +137,54 @@ void scmi_clear_smt_channel(struct scmi_smt *smt) hdr->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR; } + +/** + * Write SCMI message @msg into a SMT_MSG shared buffer @smt. + * Return 0 on success and with a negative errno in case of error. + */ +int scmi_msg_to_smt_msg(struct udevice *dev, struct scmi_smt *smt, + struct scmi_msg *msg, size_t *buf_size) +{ + struct scmi_smt_msg_header *hdr = (void *)smt->buf; + + if ((!msg->in_msg && msg->in_msg_sz) || + (!msg->out_msg && msg->out_msg_sz)) + return -EINVAL; + + if (smt->size < (sizeof(*hdr) + msg->in_msg_sz) || + smt->size < (sizeof(*hdr) + msg->out_msg_sz)) { + dev_dbg(dev, "Buffer too small\n"); + return -ETOOSMALL; + } + + *buf_size = msg->in_msg_sz + sizeof(hdr->msg_header); + + hdr->msg_header = SMT_HEADER_TOKEN(0) | + SMT_HEADER_MESSAGE_TYPE(0) | + SMT_HEADER_PROTOCOL_ID(msg->protocol_id) | + SMT_HEADER_MESSAGE_ID(msg->message_id); + + memcpy(hdr->msg_payload, msg->in_msg, msg->in_msg_sz); + + return 0; +} + +/** + * Read SCMI message from a SMT shared buffer @smt and copy it into @msg. + * Return 0 on success and with a negative errno in case of error. + */ +int scmi_msg_from_smt_msg(struct udevice *dev, struct scmi_smt *smt, + struct scmi_msg *msg, size_t buf_size) +{ + struct scmi_smt_msg_header *hdr = (void *)smt->buf; + + if (buf_size > msg->out_msg_sz + sizeof(hdr->msg_header)) { + dev_err(dev, "Buffer to small\n"); + return -ETOOSMALL; + } + + msg->out_msg_sz = buf_size - sizeof(hdr->msg_header); + memcpy(msg->out_msg, hdr->msg_payload, msg->out_msg_sz); + + return 0; +} |