Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:GA
xen.16551
5ef44e0d-x86-PMTMR-use-FADT-flags.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 5ef44e0d-x86-PMTMR-use-FADT-flags.patch of Package xen.16551
# Commit f325d2477eef8229c47d97031d314629521c70ab # Date 2020-06-25 09:11:09 +0200 # Author Grzegorz Uriasz <gorbak25@gmail.com> # Committer Jan Beulich <jbeulich@suse.com> x86/acpi: use FADT flags to determine the PMTMR width On some computers the bit width of the PM Timer as reported by ACPI is 32 bits when in fact the FADT flags report correctly that the timer is 24 bits wide. On affected machines such as the ASUS FX504GM and never gaming laptops this results in the inability to resume the machine from suspend. Without this patch suspend is broken on affected machines and even if a machine manages to resume correctly then the kernel time and xen timers are trashed. Signed-off-by: Grzegorz Uriasz <gorbak25@gmail.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/acpi/boot.c +++ b/xen/arch/x86/acpi/boot.c @@ -473,10 +473,17 @@ static int __init acpi_parse_fadt(struct #ifdef CONFIG_X86_PM_TIMER /* detect the location of the ACPI PM Timer */ - if (fadt->header.revision >= FADT2_REVISION_ID) { + if (fadt->header.revision >= FADT2_REVISION_ID && + fadt->xpm_timer_block.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { /* FADT rev. 2 */ - if (fadt->xpm_timer_block.space_id == - ACPI_ADR_SPACE_SYSTEM_IO) { + if (fadt->xpm_timer_block.access_width != 0 && + ACPI_ACCESS_BIT_WIDTH(fadt->xpm_timer_block.access_width) != 32) + printk(KERN_WARNING PREFIX "PM-Timer has invalid access width(%u)\n", + fadt->xpm_timer_block.access_width); + else if (fadt->xpm_timer_block.bit_offset != 0) + printk(KERN_WARNING PREFIX "PM-Timer has invalid bit offset(%u)\n", + fadt->xpm_timer_block.bit_offset); + else { pmtmr_ioport = fadt->xpm_timer_block.address; pmtmr_width = fadt->xpm_timer_block.bit_width; } @@ -488,8 +495,12 @@ static int __init acpi_parse_fadt(struct */ if (!pmtmr_ioport) { pmtmr_ioport = fadt->pm_timer_block; - pmtmr_width = fadt->pm_timer_length == 4 ? 24 : 0; + pmtmr_width = fadt->pm_timer_length == 4 ? 32 : 0; } + if (pmtmr_width < 32 && (fadt->flags & ACPI_FADT_32BIT_TIMER)) + printk(KERN_WARNING PREFIX "PM-Timer is too short\n"); + if (pmtmr_width > 24 && !(fadt->flags & ACPI_FADT_32BIT_TIMER)) + pmtmr_width = 24; if (pmtmr_ioport) printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x (%u bits)\n", pmtmr_ioport, pmtmr_width); --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -452,16 +452,13 @@ static u64 read_pmtimer_count(void) static s64 __init init_pmtimer(struct platform_timesource *pts) { u64 start; - u32 count, target, mask = 0xffffff; + u32 count, target, mask; - if ( !pmtmr_ioport || !pmtmr_width ) + if ( !pmtmr_ioport || (pmtmr_width != 24 && pmtmr_width != 32) ) return 0; - if ( pmtmr_width == 32 ) - { - pts->counter_bits = 32; - mask = 0xffffffff; - } + pts->counter_bits = pmtmr_width; + mask = 0xffffffff >> (32 - pmtmr_width); count = inl(pmtmr_ioport) & mask; start = rdtsc_ordered(); @@ -481,7 +478,6 @@ static struct platform_timesource __init .name = "ACPI PM Timer", .frequency = ACPI_PM_FREQUENCY, .read_counter = read_pmtimer_count, - .counter_bits = 24, .init = init_pmtimer }; --- a/xen/include/acpi/acmacros.h +++ b/xen/include/acpi/acmacros.h @@ -122,6 +122,14 @@ #endif /* + * Algorithm to obtain access bit or byte width. + * Can be used with access_width of struct acpi_generic_address and access_size of + * struct acpi_resource_generic_register. + */ +#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2)) +#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1)) + +/* * Macros for moving data around to/from buffers that are possibly unaligned. * If the hardware supports the transfer of unaligned data, just do the store. * Otherwise, we have to move one byte at a time.
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor