From 47cd1fd361e61be4c8293e02aa4b6c60c2d26d76 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:48 +0100 Subject: mailbox: mpfs-mbox: replace unbounded BUSY polling with bounded waits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MPFS mailbox driver used unbounded polling loops and treated the BUSY bit as a fatal condition in several paths. On MPFS, BUSY may be transiently reasserted even after response data is written, which is observable in U-Boot’s synchronous, polled execution model. Replace the unbounded loops with a bounded regmap_read_poll_timeout()-based helper that waits for the controller to become idle. This preserves existing behaviour while preventing infinite stalls and avoiding spurious failures during early boot. Signed-off-by: Jamie Gibbons Reviewed-by: Conor Dooley --- drivers/mailbox/mpfs-mbox.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/mailbox/mpfs-mbox.c b/drivers/mailbox/mpfs-mbox.c index b1ce377525e..165d9d89630 100644 --- a/drivers/mailbox/mpfs-mbox.c +++ b/drivers/mailbox/mpfs-mbox.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data) u32 mailbox_val, cmd_shifted, value; u8 *byte_buf; u8 idx, byte_idx, byte_offset; + int ret; u32 *word_buf = (u32 *)msg->cmd_data; @@ -86,13 +88,19 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data) regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, cmd_shifted); - do { - regmap_read(mbox->control_scb, SERVICES_CR_OFFSET, &value); - } while (SERVICE_CR_REQ_MASK == (value & SERVICE_CR_REQ_MASK)); + ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_CR_OFFSET, + value, !(value & SERVICE_CR_REQ_MASK), + 1, /* poll every 1 µs */ + 20); /* timeout 20 ms */ + if (ret) + return ret; - do { - regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &value); - } while (SERVICE_SR_BUSY_MASK == (value & SERVICE_SR_BUSY_MASK)); + ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_SR_OFFSET, + value, !(value & SERVICE_SR_BUSY_MASK), + 1, + 20); + if (ret) + return ret; msg->response->resp_status = (value >> SERVICE_SR_STATUS_SHIFT); if (msg->response->resp_status) -- cgit v1.3.1