diff options
author | David S. Miller <davem@davemloft.net> | 2013-05-24 16:48:28 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-24 16:48:28 -0700 |
commit | e6ff4c75f9095f61b3a66c2a78e47b62864022dd (patch) | |
tree | 425ea9463cbec0b1975b8a33d9a56817143055d0 /drivers/acpi/ac.c | |
parent | ee9c799c231324de681eb21e06d8bf4842768b75 (diff) | |
parent | 0e255f1c0c9add2f0c920240ac4cadc28ae274c3 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Merge net into net-next because some upcoming net-next changes
build on top of bug fixes that went into net.
Signed-off-by: David S. Miller <davem@davemloft.net>
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; } |