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

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

 



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





[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