On 8/30/2023 6:14 PM, Stephen Boyd wrote: > It's possible for the polling loop in busy_loop() to get scheduled away > for a long time. > > status = ipc_read_status(scu); > <long time scheduled away> > if (!(status & IPC_STATUS_BUSY)) > > If this happens, then the status bit could change and this function > would never test it again after checking the jiffies against the timeout > limit. Polling code should check the condition one more time after the > timeout in case this happens. I think it is not checking the condition, but reading the status one more time to reflect the latest status. > > The read_poll_timeout() helper implements this logic, and is shorter, so > simply use that helper here. > > Cc: Prashant Malani <pmalani@xxxxxxxxxxxx> > Cc: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> > Fixes: e7b7ab3847c9 ("platform/x86: intel_scu_ipc: Sleeping is fine when polling") > Signed-off-by: Stephen Boyd <swboyd@xxxxxxxxxxxx> > --- Otherwise code looks fine to me. Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@xxxxxxxxxxxxxxx> > drivers/platform/x86/intel_scu_ipc.c | 19 ++++++++----------- > 1 file changed, 8 insertions(+), 11 deletions(-) > > diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c > index 6851d10d6582..5a37becc65aa 100644 > --- a/drivers/platform/x86/intel_scu_ipc.c > +++ b/drivers/platform/x86/intel_scu_ipc.c > @@ -19,6 +19,7 @@ > #include <linux/init.h> > #include <linux/interrupt.h> > #include <linux/io.h> > +#include <linux/iopoll.h> > #include <linux/module.h> > #include <linux/slab.h> > > @@ -231,19 +232,15 @@ static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset) > /* Wait till scu status is busy */ > static inline int busy_loop(struct intel_scu_ipc_dev *scu) > { > - unsigned long end = jiffies + IPC_TIMEOUT; > - > - do { > - u32 status; > - > - status = ipc_read_status(scu); > - if (!(status & IPC_STATUS_BUSY)) > - return (status & IPC_STATUS_ERR) ? -EIO : 0; > + u8 status; > + int err; > > - usleep_range(50, 100); > - } while (time_before(jiffies, end)); > + err = read_poll_timeout(ipc_read_status, status, !(status & IPC_STATUS_BUSY), > + 100, jiffies_to_usecs(IPC_TIMEOUT), false, scu); > + if (err) > + return err; > > - return -ETIMEDOUT; > + return (status & IPC_STATUS_ERR) ? -EIO : 0; > } > > /* Wait till ipc ioc interrupt is received or timeout in 10 HZ */ -- Sathyanarayanan Kuppuswamy Linux Kernel Developer