-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ACPI: EC: Don't trust ECDT tables from ASUS
http://bugzilla.kernel.org/show_bug.cgi?id=9399 http://bugzilla.kernel.org/show_bug.cgi?id=11880 Signed-off-by: Alexey Starikovskiy <[email protected]> Signed-off-by: Len Brown <[email protected]>
- Loading branch information
Showing
1 changed file
with
30 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,31 +120,6 @@ static struct acpi_ec { | |
spinlock_t curr_lock; | ||
} *boot_ec, *first_ec; | ||
|
||
/* | ||
* Some Asus system have exchanged ECDT data/command IO addresses. | ||
*/ | ||
static int print_ecdt_error(const struct dmi_system_id *id) | ||
{ | ||
printk(KERN_NOTICE PREFIX "%s detected - " | ||
"ECDT has exchanged control/data I/O address\n", | ||
id->ident); | ||
return 0; | ||
} | ||
|
||
static struct dmi_system_id __cpuinitdata ec_dmi_table[] = { | ||
{ | ||
print_ecdt_error, "Asus L4R", { | ||
DMI_MATCH(DMI_BIOS_VERSION, "1008.006"), | ||
DMI_MATCH(DMI_PRODUCT_NAME, "L4R"), | ||
DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL}, | ||
{ | ||
print_ecdt_error, "Asus M6R", { | ||
DMI_MATCH(DMI_BIOS_VERSION, "0207"), | ||
DMI_MATCH(DMI_PRODUCT_NAME, "M6R"), | ||
DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL}, | ||
{}, | ||
}; | ||
|
||
/* -------------------------------------------------------------------------- | ||
Transaction Management | ||
-------------------------------------------------------------------------- */ | ||
|
@@ -983,8 +958,8 @@ static const struct acpi_device_id ec_device_ids[] = { | |
int __init acpi_ec_ecdt_probe(void) | ||
{ | ||
acpi_status status; | ||
struct acpi_ec *saved_ec = NULL; | ||
struct acpi_table_ecdt *ecdt_ptr; | ||
acpi_handle dummy; | ||
|
||
boot_ec = make_acpi_ec(); | ||
if (!boot_ec) | ||
|
@@ -998,21 +973,16 @@ int __init acpi_ec_ecdt_probe(void) | |
pr_info(PREFIX "EC description table is found, configuring boot EC\n"); | ||
boot_ec->command_addr = ecdt_ptr->control.address; | ||
boot_ec->data_addr = ecdt_ptr->data.address; | ||
if (dmi_check_system(ec_dmi_table)) { | ||
/* | ||
* If the board falls into ec_dmi_table, it means | ||
* that ECDT table gives the incorrect command/status | ||
* & data I/O address. Just fix it. | ||
*/ | ||
boot_ec->data_addr = ecdt_ptr->control.address; | ||
boot_ec->command_addr = ecdt_ptr->data.address; | ||
} | ||
boot_ec->gpe = ecdt_ptr->gpe; | ||
boot_ec->handle = ACPI_ROOT_OBJECT; | ||
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); | ||
/* Add some basic check against completely broken table */ | ||
if (boot_ec->data_addr != boot_ec->command_addr) | ||
/* Don't trust ECDT, which comes from ASUSTek */ | ||
if (!dmi_name_in_vendors("ASUS")) | ||
goto install; | ||
saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | ||
if (!saved_ec) | ||
return -ENOMEM; | ||
memcpy(&saved_ec, boot_ec, sizeof(saved_ec)); | ||
/* fall through */ | ||
} | ||
/* This workaround is needed only on some broken machines, | ||
|
@@ -1023,13 +993,29 @@ int __init acpi_ec_ecdt_probe(void) | |
/* Check that acpi_get_devices actually find something */ | ||
if (ACPI_FAILURE(status) || !boot_ec->handle) | ||
goto error; | ||
/* We really need to limit this workaround, the only ASUS, | ||
* which needs it, has fake EC._INI method, so use it as flag. | ||
* Keep boot_ec struct as it will be needed soon. | ||
*/ | ||
if (!dmi_name_in_vendors("ASUS") || | ||
ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy))) | ||
return -ENODEV; | ||
if (saved_ec) { | ||
/* try to find good ECDT from ASUSTek */ | ||
if (saved_ec->command_addr != boot_ec->command_addr || | ||
saved_ec->data_addr != boot_ec->data_addr || | ||
saved_ec->gpe != boot_ec->gpe || | ||
saved_ec->handle != boot_ec->handle) | ||
pr_info(PREFIX "ASUSTek keeps feeding us with broken " | ||
"ECDT tables, which are very hard to workaround. " | ||
"Trying to use DSDT EC info instead. Please send " | ||
"output of acpidump to [email protected]\n"); | ||
kfree(saved_ec); | ||
saved_ec = NULL; | ||
} else { | ||
/* We really need to limit this workaround, the only ASUS, | ||
* which needs it, has fake EC._INI method, so use it as flag. | ||
* Keep boot_ec struct as it will be needed soon. | ||
*/ | ||
acpi_handle dummy; | ||
if (!dmi_name_in_vendors("ASUS") || | ||
ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", | ||
&dummy))) | ||
return -ENODEV; | ||
} | ||
install: | ||
if (!ec_install_handlers(boot_ec)) { | ||
first_ec = boot_ec; | ||
|