diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2013-07-04 23:11:22 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2013-07-04 23:11:22 +0200 |
commit | 2b0f89317e99735bbf32eaede81f707f98ab1b5e (patch) | |
tree | 16daa236e21876b11f1c0b9256cd4046aadba020 /drivers/acpi/ac.c | |
parent | 07bd1172902e782f288e4d44b1fde7dec0f08b6f (diff) | |
parent | fa18f7bde3ad4568d1d343b60d963bfbd8dc3991 (diff) |
Merge branch 'timers/posix-cpu-timers-for-tglx' of
git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into timers/core
Frederic sayed: "Most of these patches have been hanging around for
several month now, in -mmotm for a significant chunk. They already
missed a few releases."
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/acpi/ac.c')
-rw-r--r-- | drivers/acpi/ac.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 00d2efd674df..4f4e741d34b2 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -28,6 +28,8 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/types.h> +#include <linux/dmi.h> +#include <linux/delay.h> #ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> @@ -74,6 +76,8 @@ static int acpi_ac_resume(struct device *dev); #endif static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); +static int ac_sleep_before_get_state_ms; + static struct acpi_driver acpi_ac_driver = { .name = "ac", .class = ACPI_AC_CLASS, @@ -252,6 +256,16 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) case ACPI_AC_NOTIFY_STATUS: case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: + /* + * A buggy BIOS may notify AC first and then sleep for + * a specific time before doing actual operations in the + * EC event handler (_Qxx). This will cause the AC state + * reported by the ACPI event to be incorrect, so wait for a + * specific time for the EC event handler to make progress. + */ + if (ac_sleep_before_get_state_ms > 0) + msleep(ac_sleep_before_get_state_ms); + acpi_ac_get_state(ac); acpi_bus_generate_proc_event(device, event, (u32) ac->state); acpi_bus_generate_netlink_event(device->pnp.device_class, @@ -264,6 +278,24 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) return; } +static int thinkpad_e530_quirk(const struct dmi_system_id *d) +{ + ac_sleep_before_get_state_ms = 1000; + return 0; +} + +static struct dmi_system_id ac_dmi_table[] = { + { + .callback = thinkpad_e530_quirk, + .ident = "thinkpad e530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"), + }, + }, + {}, +}; + static int acpi_ac_add(struct acpi_device *device) { int result = 0; @@ -312,6 +344,7 @@ static int acpi_ac_add(struct acpi_device *device) kfree(ac); } + dmi_check_system(ac_dmi_table); return result; } |