Skip to content

Commit

Permalink
Merge tag 'scmi-fixes-6.12' of https://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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]>
  • Loading branch information
arndb committed Oct 15, 2024
2 parents aa56d75 + da1642b commit 1b59d6c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 16 deletions.
4 changes: 1 addition & 3 deletions drivers/firmware/arm_scmi/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 4 additions & 2 deletions drivers/firmware/arm_scmi/transports/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down
32 changes: 21 additions & 11 deletions drivers/firmware/arm_scmi/transports/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -267,27 +270,34 @@ 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,
struct scmi_xfer *__unused)
{
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,
Expand Down

0 comments on commit 1b59d6c

Please sign in to comment.