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. 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. 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... 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) -- 2.43.0