aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <[email protected]>2024-10-15 20:39:42 +0000
committerArnd Bergmann <[email protected]>2024-10-15 20:39:43 +0000
commit1b59d6c19c2ca4e705effee5c2f68fd8ab307c90 (patch)
treeebe0ce0630ad6434dfb3118433979d8f425e2834
parentaa56d752673aaec3cab7d73c668c4b29925d3ba0 (diff)
parentda1642bc97c4ef67f347edcd493bd0a52f88777b (diff)
Merge tag 'scmi-fixes-6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes
Arm SCMI fixes for v6.12 Couple of fixes to address the issues found and reported on Broadcom STB platforms following the recent refactor of all the SCMI transports as standalone drivers. One of the issue is that the effective timeout value is much less than the intended value due to the way mailbox messages are queues in the mailbox framework. Since we block or serialise the shmem access anyway, there is no point in utilizing mailbox queues. The issue is fixed with exclusive lock on the channel when sending the message. The other issues is actually non-issue for upstream, but the workaround is just changing the link order of the transport drivers which enables Broadcom STB platforms to run both upstream and custom downstream kernel without any device tree changes. So pushing this to help them test upstream seamlessly as it has no practical or theoretical impact for others. There is also a fix to address possible double freeing of the name string in scmi_debugfs_common_cleanup() when devm_add_action_or_reset() fails. * tag 'scmi-fixes-6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Queue in scmi layer for mailbox implementation firmware: arm_scmi: Give SMC transport precedence over mailbox firmware: arm_scmi: Fix the double free in scmi_debugfs_common_setup() Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
-rw-r--r--drivers/firmware/arm_scmi/driver.c4
-rw-r--r--drivers/firmware/arm_scmi/transports/Makefile6
-rw-r--r--drivers/firmware/arm_scmi/transports/mailbox.c32
3 files changed, 26 insertions, 16 deletions
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 88c5c4ff4bb6..a477b5ade38d 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -2976,10 +2976,8 @@ static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info)
dbg->top_dentry = top_dentry;
if (devm_add_action_or_reset(info->dev,
- scmi_debugfs_common_cleanup, dbg)) {
- scmi_debugfs_common_cleanup(dbg);
+ scmi_debugfs_common_cleanup, dbg))
return NULL;
- }
return dbg;
}
diff --git a/drivers/firmware/arm_scmi/transports/Makefile b/drivers/firmware/arm_scmi/transports/Makefile
index 362a406f08e6..3ba3d3bee151 100644
--- a/drivers/firmware/arm_scmi/transports/Makefile
+++ b/drivers/firmware/arm_scmi/transports/Makefile
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
-scmi_transport_mailbox-objs := mailbox.o
-obj-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += scmi_transport_mailbox.o
+# Keep before scmi_transport_mailbox.o to allow precedence
+# while matching the compatible.
scmi_transport_smc-objs := smc.o
obj-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += scmi_transport_smc.o
+scmi_transport_mailbox-objs := mailbox.o
+obj-$(CONFIG_ARM_SCMI_TRANSPORT_MAILBOX) += scmi_transport_mailbox.o
scmi_transport_optee-objs := optee.o
obj-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += scmi_transport_optee.o
scmi_transport_virtio-objs := virtio.o
diff --git a/drivers/firmware/arm_scmi/transports/mailbox.c b/drivers/firmware/arm_scmi/transports/mailbox.c
index 1a754dee24f7..e3d5f7560990 100644
--- a/drivers/firmware/arm_scmi/transports/mailbox.c
+++ b/drivers/firmware/arm_scmi/transports/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
+ * @chan_lock: Lock that prevents multiple xfers from being queued
*/
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 mutex chan_lock;
};
#define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl)
@@ -238,6 +240,7 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
cinfo->transport_info = smbox;
smbox->cinfo = cinfo;
+ mutex_init(&smbox->chan_lock);
return 0;
}
@@ -267,13 +270,23 @@ static int mailbox_send_message(struct scmi_chan_info *cinfo,
struct scmi_mailbox *smbox = cinfo->transport_info;
int ret;
- ret = mbox_send_message(smbox->chan, xfer);
+ /*
+ * The mailbox layer has its own queue. However the mailbox queue
+ * confuses the per message SCMI timeouts since the clock starts when
+ * the message is submitted into the mailbox queue. So when multiple
+ * messages are queued up the clock starts on all messages instead of
+ * only the one inflight.
+ */
+ mutex_lock(&smbox->chan_lock);
- /* mbox_send_message returns non-negative value on success, so reset */
- if (ret > 0)
- ret = 0;
+ ret = mbox_send_message(smbox->chan, xfer);
+ /* mbox_send_message returns non-negative value on success */
+ if (ret < 0) {
+ mutex_unlock(&smbox->chan_lock);
+ return ret;
+ }
- return ret;
+ return 0;
}
static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret,
@@ -281,13 +294,10 @@ static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret,
{
struct scmi_mailbox *smbox = cinfo->transport_info;
- /*
- * NOTE: we might prefer not to need the mailbox ticker to manage the
- * transfer queueing since the protocol layer queues things by itself.
- * Unfortunately, we have to kick the mailbox framework after we have
- * received our message.
- */
mbox_client_txdone(smbox->chan, ret);
+
+ /* Release channel */
+ mutex_unlock(&smbox->chan_lock);
}
static void mailbox_fetch_response(struct scmi_chan_info *cinfo,