lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <2803b89021f991662b000f50e45dbaebdcca438a.1724729626.git.len.brown@intel.com>
Date: Mon, 26 Aug 2024 23:35:18 -0400
From: Len Brown <lenb@...nel.org>
To: rjw@...ysocki.net
Cc: linux-acpi@...r.kernel.org,
	linux-pm@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	Len Brown <len.brown@...el.com>,
	Arjan van de Ven <arjan@...ux.intel.com>,
	Todd Brandt <todd.e.brandt@...el.com>
Subject: [PATCH] ACPI: Remove msleep() bloat from acpi_os_sleep()

From: Len Brown <len.brown@...el.com>

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@...el.com>
Suggested-by: Arjan van de Ven <arjan@...ux.intel.com>
Tested-by: Todd Brandt <todd.e.brandt@...el.com>
---
 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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ