Skip to content

Commit

Permalink
ACPICA: FADT: set acpi_gbl_use_default_register_widths to TRUE by def…
Browse files Browse the repository at this point in the history
…ault

This returns the FADT support to the original behavior, which is
to use default register widths. However, now check each register
definition and report a warning if it differs from the default.
This is a first step to moving away from the default widths,
rather than outright believing the widths in all FADTs for all
machines, considered rather dangerous until more data is obtained.

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
robert.moore@intel.com authored and Len Brown committed Dec 31, 2008
1 parent 06f5541 commit 4b67a0e
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 69 deletions.
173 changes: 105 additions & 68 deletions drivers/acpi/tables/tbfadt.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ static void acpi_tb_validate_fadt(void);

typedef struct acpi_fadt_info {
char *name;
u8 target;
u8 source;
u8 address64;
u8 address32;
u8 length;
u8 default_length;
u8 type;

} acpi_fadt_info;
Expand All @@ -72,37 +73,61 @@ typedef struct acpi_fadt_info {
#define ACPI_FADT_SEPARATE_LENGTH 2

static struct acpi_fadt_info fadt_info_table[] = {
{"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block),
{"Pm1aEventBlock",
ACPI_FADT_OFFSET(xpm1a_event_block),
ACPI_FADT_OFFSET(pm1a_event_block),
ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED},
ACPI_FADT_OFFSET(pm1_event_length),
ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
ACPI_FADT_REQUIRED},

{"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block),
{"Pm1bEventBlock",
ACPI_FADT_OFFSET(xpm1b_event_block),
ACPI_FADT_OFFSET(pm1b_event_block),
ACPI_FADT_OFFSET(pm1_event_length), 0},
ACPI_FADT_OFFSET(pm1_event_length),
ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
0},

{"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block),
{"Pm1aControlBlock",
ACPI_FADT_OFFSET(xpm1a_control_block),
ACPI_FADT_OFFSET(pm1a_control_block),
ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED},
ACPI_FADT_OFFSET(pm1_control_length),
ACPI_PM1_REGISTER_WIDTH,
ACPI_FADT_REQUIRED},

{"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block),
{"Pm1bControlBlock",
ACPI_FADT_OFFSET(xpm1b_control_block),
ACPI_FADT_OFFSET(pm1b_control_block),
ACPI_FADT_OFFSET(pm1_control_length), 0},
ACPI_FADT_OFFSET(pm1_control_length),
ACPI_PM1_REGISTER_WIDTH,
0},

{"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block),
{"Pm2ControlBlock",
ACPI_FADT_OFFSET(xpm2_control_block),
ACPI_FADT_OFFSET(pm2_control_block),
ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH},
ACPI_FADT_OFFSET(pm2_control_length),
ACPI_PM2_REGISTER_WIDTH,
ACPI_FADT_SEPARATE_LENGTH},

{"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block),
{"PmTimerBlock",
ACPI_FADT_OFFSET(xpm_timer_block),
ACPI_FADT_OFFSET(pm_timer_block),
ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED},
ACPI_FADT_OFFSET(pm_timer_length),
ACPI_PM_TIMER_WIDTH,
ACPI_FADT_REQUIRED},

{"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block),
{"Gpe0Block",
ACPI_FADT_OFFSET(xgpe0_block),
ACPI_FADT_OFFSET(gpe0_block),
ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH},
ACPI_FADT_OFFSET(gpe0_block_length),
0,
ACPI_FADT_SEPARATE_LENGTH},

{"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block),
{"Gpe1Block",
ACPI_FADT_OFFSET(xgpe1_block),
ACPI_FADT_OFFSET(gpe1_block),
ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH}
ACPI_FADT_OFFSET(gpe1_block_length),
0,
ACPI_FADT_SEPARATE_LENGTH}
};

#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info))
Expand Down Expand Up @@ -279,8 +304,9 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)

static void acpi_tb_convert_fadt(void)
{
u8 pm1_register_length;
struct acpi_generic_address *target;
u8 pm1_register_bit_width;
u8 pm1_register_byte_width;
struct acpi_generic_address *target64;
u32 i;

/* Update the local FADT table header length */
Expand Down Expand Up @@ -326,21 +352,22 @@ static void acpi_tb_convert_fadt(void)
}

/*
* Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X"
* generic address structures as necessary.
* Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
* generic address structures as necessary. Later code will always use
* the 64-bit address structures.
*/
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
target =
target64 =
ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
fadt_info_table[i].target);
fadt_info_table[i].address64);

/* Expand only if the X target is null */
/* Expand only if the 64-bit X target is null */

if (!target->address) {
if (!target64->address) {

/* The space_id is always I/O for the legacy address fields */
/* The space_id is always I/O for the 32-bit legacy address fields */

acpi_tb_init_generic_address(target,
acpi_tb_init_generic_address(target64,
ACPI_ADR_SPACE_SYSTEM_IO,
*ACPI_ADD_PTR(u8,
&acpi_gbl_FADT,
Expand All @@ -350,7 +377,7 @@ static void acpi_tb_convert_fadt(void)
&acpi_gbl_FADT,
fadt_info_table
[i].
source));
address32));
}
}

Expand All @@ -359,19 +386,53 @@ static void acpi_tb_convert_fadt(void)
acpi_tb_validate_fadt();

/*
* Get the length of the individual PM1 registers. Each register is
* defined to be the event block length / 2.
* Optionally check all register lengths against the default values and
* update them if they are incorrect.
*/
pm1_register_length = (u8)ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
if (acpi_gbl_use_default_register_widths) {
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
target64 =
ACPI_ADD_PTR(struct acpi_generic_address,
&acpi_gbl_FADT,
fadt_info_table[i].address64);

/*
* If a valid register (Address != 0) and the (default_length > 0)
* (Not a GPE register), then check the width against the default.
*/
if ((target64->address) &&
(fadt_info_table[i].default_length > 0) &&
(fadt_info_table[i].default_length !=
target64->bit_width)) {
ACPI_WARNING((AE_INFO,
"Invalid length for %s: %d, using default %d",
fadt_info_table[i].name,
target64->bit_width,
fadt_info_table[i].
default_length));

/* Incorrect size, set width to the default */

target64->bit_width =
fadt_info_table[i].default_length;
}
}
}

/*
* Get the length of the individual PM1 registers (enable and status).
* Each register is defined to be (event block length / 2).
*/
pm1_register_bit_width =
(u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width);
pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width);

/*
* Adjust the lengths of the PM1 Event Blocks so that they can be used to
* access the PM1 status register(s).
* access the PM1 status register(s). Use (width / 2)
*/
acpi_gbl_FADT.xpm1a_event_block.bit_width =
(u8)ACPI_MUL_8(pm1_register_length);
acpi_gbl_FADT.xpm1b_event_block.bit_width =
(u8)ACPI_MUL_8(pm1_register_length);
acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width;
acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width;

/*
* Calculate separate GAS structs for the PM1 Enable registers.
Expand All @@ -398,9 +459,9 @@ static void acpi_tb_convert_fadt(void)

acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
acpi_gbl_FADT.xpm1a_event_block.space_id,
pm1_register_length,
pm1_register_byte_width,
(acpi_gbl_FADT.xpm1a_event_block.address +
pm1_register_length));
pm1_register_byte_width));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1a_enable.space_id =
acpi_gbl_FADT.xpm1a_event_block.space_id;
Expand All @@ -417,38 +478,14 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_FADT.pm1_event_length);
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
acpi_gbl_FADT.xpm1b_event_block.space_id,
pm1_register_length,
pm1_register_byte_width,
(acpi_gbl_FADT.xpm1b_event_block.
address + pm1_register_length));
address + pm1_register_byte_width));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1b_enable.space_id =
acpi_gbl_FADT.xpm1b_event_block.space_id;

}

if (acpi_gbl_use_default_register_widths) {
/*
* Optionally, use the default sizes for the ACPI registers.
* Some FADTs do not have the correct length(s).
*
* Note: Xpm1a_event_block and Xpm1b_event_block are used to access the PM1
* status registers. The PM1 enable registers are created above.
*/
acpi_gbl_xpm1a_enable.bit_width = ACPI_PM1_REGISTER_WIDTH;
acpi_gbl_xpm1b_enable.bit_width = ACPI_PM1_REGISTER_WIDTH;

acpi_gbl_FADT.xpm1a_event_block.bit_width =
ACPI_PM1_REGISTER_WIDTH;
acpi_gbl_FADT.xpm1b_event_block.bit_width =
ACPI_PM1_REGISTER_WIDTH;
acpi_gbl_FADT.xpm1a_control_block.bit_width =
ACPI_PM1_REGISTER_WIDTH;
acpi_gbl_FADT.xpm1b_control_block.bit_width =
ACPI_PM1_REGISTER_WIDTH;
acpi_gbl_FADT.xpm2_control_block.bit_width =
ACPI_PM2_REGISTER_WIDTH;
acpi_gbl_FADT.xpm_timer_block.bit_width = ACPI_PM_TIMER_WIDTH;
}
}

/******************************************************************************
Expand Down Expand Up @@ -511,18 +548,18 @@ static void acpi_tb_validate_fadt(void)
*/
address64 = ACPI_ADD_PTR(struct acpi_generic_address,
&acpi_gbl_FADT,
fadt_info_table[i].target);
fadt_info_table[i].address64);
address32 =
ACPI_ADD_PTR(u32, &acpi_gbl_FADT,
fadt_info_table[i].source);
fadt_info_table[i].address32);
length =
*ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
fadt_info_table[i].length);
name = fadt_info_table[i].name;

/*
* For each extended field, check for length mismatch between the
* legacy length field and the corresonding 64-bit X length field.
* legacy length field and the corresponding 64-bit X length field.
*/
if (address64 && (address64->bit_width != ACPI_MUL_8(length))) {
ACPI_WARNING((AE_INFO,
Expand Down
2 changes: 1 addition & 1 deletion include/acpi/acglobal.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
* Optionally use default values for the ACPI register widths. Set this to
* TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, FALSE);
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);

/*****************************************************************************
*
Expand Down

0 comments on commit 4b67a0e

Please sign in to comment.