Skip to content

Commit c23c03b

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Fix timeout checks on polling path
Polling mode transactions wait for a reply busy-looping without holding a spinlock, but currently the timeout checks are based only on elapsed time: as a result we could hit a false positive whenever our busy-looping thread is pre-empted and scheduled out for a time greater than the polling timeout. Change the checks at the end of the busy-loop to make sure that the polling wasn't indeed successful or an out-of-order reply caused the polling to be forcibly terminated. Fixes: 31d2f80 ("firmware: arm_scmi: Add sync_cmds_completed_on_ret transport flag") Reported-by: Huangjie <huangjie1663@phytium.com.cn> Closes: https://lore.kernel.org/arm-scmi/20250123083323.2363749-1-jackhuang021@gmail.com/ Signed-off-by: Cristian Marussi <cristian.marussi@arm.com> Cc: stable@vger.kernel.org # 5.18.x Message-Id: <20250310175800.1444293-1-cristian.marussi@arm.com> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
1 parent 9ca6784 commit c23c03b

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

drivers/firmware/arm_scmi/driver.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,8 @@ static void xfer_put(const struct scmi_protocol_handle *ph,
12481248
}
12491249

12501250
static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
1251-
struct scmi_xfer *xfer, ktime_t stop)
1251+
struct scmi_xfer *xfer, ktime_t stop,
1252+
bool *ooo)
12521253
{
12531254
struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
12541255

@@ -1257,7 +1258,7 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
12571258
* in case of out-of-order receptions of delayed responses
12581259
*/
12591260
return info->desc->ops->poll_done(cinfo, xfer) ||
1260-
try_wait_for_completion(&xfer->done) ||
1261+
(*ooo = try_wait_for_completion(&xfer->done)) ||
12611262
ktime_after(ktime_get(), stop);
12621263
}
12631264

@@ -1274,15 +1275,17 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
12741275
* itself to support synchronous commands replies.
12751276
*/
12761277
if (!desc->sync_cmds_completed_on_ret) {
1278+
bool ooo = false;
1279+
12771280
/*
12781281
* Poll on xfer using transport provided .poll_done();
12791282
* assumes no completion interrupt was available.
12801283
*/
12811284
ktime_t stop = ktime_add_ms(ktime_get(), timeout_ms);
12821285

1283-
spin_until_cond(scmi_xfer_done_no_timeout(cinfo,
1284-
xfer, stop));
1285-
if (ktime_after(ktime_get(), stop)) {
1286+
spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer,
1287+
stop, &ooo));
1288+
if (!ooo && !info->desc->ops->poll_done(cinfo, xfer)) {
12861289
dev_err(dev,
12871290
"timed out in resp(caller: %pS) - polling\n",
12881291
(void *)_RET_IP_);

0 commit comments

Comments
 (0)