Re: [PATCH] ACPI: Remove msleep() bloat from acpi_os_sleep()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



First, let me add a few people who know more about timers than I do.

On Tue, Aug 27, 2024 at 5:42 AM Len Brown <lenb@xxxxxxxxxx> wrote:
>
> From: Len Brown <len.brown@xxxxxxxxx>
>
> Optimize acpi_os_sleep(ms) using usleep_range(floor, ceiling).
> The floor of the range is the exact requested ms,
> with an additional 1ms of slack for sleeps above 20ms.
>
> This reduces  the kernel resume time of the Dell 9300
> to 1,124 ms from 2,471 ms.
>
> The ACPI AML Sleep(ms) method calls acpi_os_sleep(ms),
> which has invoked msleep(ms) since 2013.
>
> But msleep(ms) is based on jiffies, and the rounding-up
> logic to convert to jiffies on a HZ=250 system causes
> msleep(5) to bloat to a minimum of a 12ms delay.
> msleep(5) typically takes over 15ms!
>
> As a result, AML delay loops with small Sleep() inside
> magnify the entire loop.  A particularly painful example
> is ACPI support for powering-on ICL and TGL
> thunderbolt/pcie_ports during system resume.
>
> Regarding jiffy-based msleep() being inexpensive
> and hrtimer-based usleep_range() being expensive.
> ACPI AML timer invocations are rare, and so it
> is unlikely the hrtimer cost will be noticible,
> or even measurable.  At the same time, the msleep()
> timer duration bloat is significant enough to
> be noticed by end users.

I'm not sure why you are refusing to follow the implementation of
fsleep() and Documentation/timers/timers-howto.rst and still use
msleep() for sleep durations longer than 20 ms.

Why should usleep_range() be used for 100 ms sleeps, for instance?
This goes against the recommendation in the above document, so is
there a particular reason?

> Regarding usleep_range() timer coalescing.
> It virtually never works during ACPI flows, which
> commonly run when there are few coalescing
> opportunities. As a result, the timers almost
> always expire at the maximum end of their specified range.

I don't think that's the main point of using a nonzero range in
usleep_range().  AFAICS, this is about letting the timekeeping
subsystem know how much you care about timer precision so it can
arrange things to meet everyone's needs.

> It was tempting to use usleep_range(us, us)
> for all values of us.  But 1 ms is added to the
> range for timers over 20ms on the reasoning that
> the AML Sleep interface has a granularity of 1ms,
> most costly loops use duration under 20ms inside,
> and singular long sleeps are unlitly to notice an
> additiona 1ms, so why not allow some coalescing...

So again, why not use msleep() for sleeps longer than 20 ms?

> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=216263
> Signed-off-by: Len Brown <len.brown@xxxxxxxxx>
> Suggested-by: Arjan van de Ven <arjan@xxxxxxxxxxxxxxx>
> Tested-by: Todd Brandt <todd.e.brandt@xxxxxxxxx>
> ---
>  drivers/acpi/osl.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
> index 70af3fbbebe5..c4c76f86cd7a 100644
> --- a/drivers/acpi/osl.c
> +++ b/drivers/acpi/osl.c
> @@ -607,7 +607,13 @@ acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
>
>  void acpi_os_sleep(u64 ms)
>  {
> -       msleep(ms);
> +       u64 us = ms * 1000;
> +
> +       if (us <= 20000)
> +               usleep_range(us, us);
> +       else
> +               usleep_range(us, us + 1000);
> +
>  }
>
>  void acpi_os_stall(u32 us)
> --

While I agree with using usleep_range() for sleeps up to 20 ms in
acpi_os_sleep(), I disagree with the patch as is.

Thanks!





[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux