Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01a5bba5 authored by Jan Beulich's avatar Jan Beulich Committed by Andi Kleen
Browse files

Fix FADT parsing



The (1.0 inherited) separate length fields in the FADT are byte granular.
Further, PM1a/b may have distinct lengths and live in distinct address spaces.
 acpi_tb_convert_fadt() should account for all of these conditions.

Apart from these changes I'm puzzled by the fact that, not just for
acpi_gbl_xpm1{a,b}_enable, acpi_hw_low_level_{read,write}() get an explicit
size passed rather than using the size found in the passed GAS.  What happens
on a platform that defines PM1{a,b} wider than 16 bits?  Of course,
acpi_hw_low_level_{read,write}() at present are entirely un-prepared to deal
with sizes other than 8, 16, or 32, not to speak of a non-zero bit_offset or
access_width...

Signed-off-by: default avatarJan Beulich <jbeulich@novell.com>
Signed-off-by: default avatarAndi Kleen <ak@linux.intel.com>
Cc: Len Brown <lenb@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 4d387043
Loading
Loading
Loading
Loading
+11 −6
Original line number Original line Diff line number Diff line
@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = {


static void inline
static void inline
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
			     u8 bit_width, u64 address)
			     u8 byte_width, u64 address)
{
{


	/*
	/*
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
	/* All other fields are byte-wide */
	/* All other fields are byte-wide */


	generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
	generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
	generic_address->bit_width = bit_width;
	generic_address->bit_width = byte_width << 3;
	generic_address->bit_offset = 0;
	generic_address->bit_offset = 0;
	generic_address->access_width = 0;
	generic_address->access_width = 0;
}
}
@@ -343,9 +343,11 @@ static void acpi_tb_convert_fadt(void)
	 *
	 *
	 * The PM event blocks are split into two register blocks, first is the
	 * The PM event blocks are split into two register blocks, first is the
	 * PM Status Register block, followed immediately by the PM Enable Register
	 * PM Status Register block, followed immediately by the PM Enable Register
	 * block. Each is of length (pm1_event_length/2)
	 * block. Each is of length (xpm1x_event_block.bit_width/2)
	 */
	 */
	pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
	WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1a_event_block.bit_width));
	pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
					       .xpm1a_event_block.bit_width);


	/* The PM1A register block is required */
	/* The PM1A register block is required */


@@ -360,14 +362,17 @@ static void acpi_tb_convert_fadt(void)
	/* The PM1B register block is optional, ignore if not present */
	/* The PM1B register block is optional, ignore if not present */


	if (acpi_gbl_FADT.xpm1b_event_block.address) {
	if (acpi_gbl_FADT.xpm1b_event_block.address) {
		WARN_ON(ACPI_MOD_16(acpi_gbl_FADT.xpm1b_event_block.bit_width));
		pm1_register_length = (u8) ACPI_DIV_16(acpi_gbl_FADT
						       .xpm1b_event_block
						       .bit_width);
		acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
		acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
					     pm1_register_length,
					     pm1_register_length,
					     (acpi_gbl_FADT.xpm1b_event_block.
					     (acpi_gbl_FADT.xpm1b_event_block.
					      address + pm1_register_length));
					      address + pm1_register_length));
		/* Don't forget to copy space_id of the GAS */
		/* Don't forget to copy space_id of the GAS */
		acpi_gbl_xpm1b_enable.space_id =
		acpi_gbl_xpm1b_enable.space_id =
		    acpi_gbl_FADT.xpm1a_event_block.space_id;
		    acpi_gbl_FADT.xpm1b_event_block.space_id;

	}
	}
}
}