Skip to content

Commit da1642b

Browse files
Ryceancurrysudeep-holla
authored andcommitted
firmware: arm_scmi: Queue in scmi layer for mailbox implementation
send_message() does not block in the MBOX implementation. This is because the mailbox layer has its own queue. However, this confuses the per xfer timeouts as they all start their timeout ticks in parallel. Consider a case where the xfer timeout is 30ms and a SCMI transaction takes 25ms: | 0ms: Message #0 is queued in mailbox layer and sent out, then sits | at scmi_wait_for_message_response() with a timeout of 30ms | 1ms: Message #1 is queued in mailbox layer but not sent out yet. | Since send_message() doesn't block, it also sits at | scmi_wait_for_message_response() with a timeout of 30ms | ... | 25ms: Message #0 is completed, txdone is called and message #1 is sent | 31ms: Message #1 times out since the count started at 1ms. Even though | it has only been inflight for 6ms. Fixes: 5c8a47a ("firmware: arm_scmi: Make scmi core independent of the transport type") Signed-off-by: Justin Chen <[email protected]> Message-Id: <[email protected]> Reviewed-by: Cristian Marussi <[email protected]> Tested-by: Cristian Marussi <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent db8f0b8 commit da1642b

File tree

1 file changed

+21
-11
lines changed
  • drivers/firmware/arm_scmi/transports

1 file changed

+21
-11
lines changed

drivers/firmware/arm_scmi/transports/mailbox.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* @chan_platform_receiver: Optional Platform Receiver mailbox unidirectional channel
2626
* @cinfo: SCMI channel info
2727
* @shmem: Transmit/Receive shared memory area
28+
* @chan_lock: Lock that prevents multiple xfers from being queued
2829
*/
2930
struct scmi_mailbox {
3031
struct mbox_client cl;
@@ -33,6 +34,7 @@ struct scmi_mailbox {
3334
struct mbox_chan *chan_platform_receiver;
3435
struct scmi_chan_info *cinfo;
3536
struct scmi_shared_mem __iomem *shmem;
37+
struct mutex chan_lock;
3638
};
3739

3840
#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,
238240

239241
cinfo->transport_info = smbox;
240242
smbox->cinfo = cinfo;
243+
mutex_init(&smbox->chan_lock);
241244

242245
return 0;
243246
}
@@ -267,27 +270,34 @@ static int mailbox_send_message(struct scmi_chan_info *cinfo,
267270
struct scmi_mailbox *smbox = cinfo->transport_info;
268271
int ret;
269272

270-
ret = mbox_send_message(smbox->chan, xfer);
273+
/*
274+
* The mailbox layer has its own queue. However the mailbox queue
275+
* confuses the per message SCMI timeouts since the clock starts when
276+
* the message is submitted into the mailbox queue. So when multiple
277+
* messages are queued up the clock starts on all messages instead of
278+
* only the one inflight.
279+
*/
280+
mutex_lock(&smbox->chan_lock);
271281

272-
/* mbox_send_message returns non-negative value on success, so reset */
273-
if (ret > 0)
274-
ret = 0;
282+
ret = mbox_send_message(smbox->chan, xfer);
283+
/* mbox_send_message returns non-negative value on success */
284+
if (ret < 0) {
285+
mutex_unlock(&smbox->chan_lock);
286+
return ret;
287+
}
275288

276-
return ret;
289+
return 0;
277290
}
278291

279292
static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret,
280293
struct scmi_xfer *__unused)
281294
{
282295
struct scmi_mailbox *smbox = cinfo->transport_info;
283296

284-
/*
285-
* NOTE: we might prefer not to need the mailbox ticker to manage the
286-
* transfer queueing since the protocol layer queues things by itself.
287-
* Unfortunately, we have to kick the mailbox framework after we have
288-
* received our message.
289-
*/
290297
mbox_client_txdone(smbox->chan, ret);
298+
299+
/* Release channel */
300+
mutex_unlock(&smbox->chan_lock);
291301
}
292302

293303
static void mailbox_fetch_response(struct scmi_chan_info *cinfo,

0 commit comments

Comments
 (0)