Skip to content

Commit bede543

Browse files
committed
ACPI: OSL: Use usleep_range() in acpi_os_sleep()
As stated by Len in [1], the extra delay added by msleep() to the sleep time value passed to it can be significant, roughly between 1.5 ns on systems with HZ = 1000 and as much as 15 ms on systems with HZ = 100, which is hardly acceptable, at least for small sleep time values. msleep(5) on the default HZ = 250 in Ubuntu on a modern PC takes about 12 ms. This results in over 800 ms of spurious system resume delay on systems such as the Dell XPS-13-9300, which use ASL Sleep(5ms) in a tight loop. Address this by using usleep_range() in acpi_os_sleep() instead of msleep(). For short sleep times this is a no brainer, but even for long sleeps usleep_range() should be preferred because timer wheel timers are optimized for cancelation before they expire and this particular timer is not going to be canceled. Add at least 50 us on top of the requested sleep time in case the timer can be subject to coalescing, which is consistent with what's done in user space in this context [2], but for sleeps longer than 5 ms use 1% of the requested sleep time for this purpose. The rationale here is that longer sleeps don't need that much of a timer precision as a rule and making the timer a more likely candidate for coalescing in these cases is generally desirable. It starts at 5 ms so that the delta between the requested sleep time and the effective deadline is a contiuous function of the former. Link: https://lore.kernel.org/linux-pm/c7db7e804c453629c116d508558eaf46477a2d73.1731708405.git.len.brown@intel.com/ [1] Link: https://lore.kernel.org/linux-pm/CAJvTdK=Q1kwWA6Wxn8Zcf0OicDEk6cHYFAvQVizgA47mXu63+g@mail.gmail.com/ [2] Closes: https://bugzilla.kernel.org/show_bug.cgi?id=216263 Reported-by: Len Brown <lenb@kernel.org> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Tested-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://patch.msgid.link/5857066.DvuYhMxLoT@rjwysocki.net
1 parent fac04ef commit bede543

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

drivers/acpi/osl.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,27 @@ acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
607607

608608
void acpi_os_sleep(u64 ms)
609609
{
610-
msleep(ms);
610+
u64 usec = ms * USEC_PER_MSEC, delta_us = 50;
611+
612+
/*
613+
* Use a hrtimer because the timer wheel timers are optimized for
614+
* cancelation before they expire and this timer is not going to be
615+
* canceled.
616+
*
617+
* Set the delta between the requested sleep time and the effective
618+
* deadline to at least 50 us in case there is an opportunity for timer
619+
* coalescing.
620+
*
621+
* Moreover, longer sleeps can be assumed to need somewhat less timer
622+
* precision, so sacrifice some of it for making the timer a more likely
623+
* candidate for coalescing by setting the delta to 1% of the sleep time
624+
* if it is above 5 ms (this value is chosen so that the delta is a
625+
* continuous function of the sleep time).
626+
*/
627+
if (ms > 5)
628+
delta_us = (USEC_PER_MSEC / 100) * ms;
629+
630+
usleep_range(usec, usec + delta_us);
611631
}
612632

613633
void acpi_os_stall(u32 us)

0 commit comments

Comments
 (0)