diff options
Diffstat (limited to 'drivers/acpi/bus.c')
-rw-r--r-- | drivers/acpi/bus.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a52126e46307..9042a8579668 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -32,6 +32,7 @@ #include <linux/device.h> #include <linux/proc_fs.h> #include <linux/acpi.h> +#include <linux/slab.h> #ifdef CONFIG_X86 #include <asm/mpspec.h> #endif @@ -68,6 +69,44 @@ static struct dmi_system_id __cpuinitdata power_nocheck_dmi_table[] = { }; +#ifdef CONFIG_X86 +static int set_copy_dsdt(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE "%s detected - " + "force copy of DSDT to local memory\n", id->ident); + acpi_gbl_copy_dsdt_locally = 1; + return 0; +} + +static struct dmi_system_id dsdt_dmi_table[] __initdata = { + /* + * Insyde BIOS on some TOSHIBA machines corrupt the DSDT. + * https://bugzilla.kernel.org/show_bug.cgi?id=14679 + */ + { + .callback = set_copy_dsdt, + .ident = "TOSHIBA Satellite A505", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"), + }, + }, + { + .callback = set_copy_dsdt, + .ident = "TOSHIBA Satellite L505D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"), + }, + }, + {} +}; +#else +static struct dmi_system_id dsdt_dmi_table[] __initdata = { + {} +}; +#endif + /* -------------------------------------------------------------------------- Device Management -------------------------------------------------------------------------- */ @@ -190,16 +229,16 @@ int acpi_bus_get_power(acpi_handle handle, int *state) * Get the device's power state either directly (via _PSC) or * indirectly (via power resources). */ - if (device->power.flags.explicit_get) { + if (device->power.flags.power_resources) { + result = acpi_power_get_inferred_state(device); + if (result) + return result; + } else if (device->power.flags.explicit_get) { status = acpi_evaluate_integer(device->handle, "_PSC", NULL, &psc); if (ACPI_FAILURE(status)) return -ENODEV; device->power.state = (int)psc; - } else if (device->power.flags.power_resources) { - result = acpi_power_get_inferred_state(device); - if (result) - return result; } *state = device->power.state; @@ -526,7 +565,7 @@ int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, if (!event_is_open) return 0; - event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); + event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); if (!event) return -ENOMEM; @@ -812,6 +851,12 @@ void __init acpi_early_init(void) acpi_gbl_permanent_mmap = 1; + /* + * If the machine falls into the DMI check table, + * DSDT will be copied to memory + */ + dmi_check_system(dsdt_dmi_table); + status = acpi_reallocate_root_table(); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX |