From 86f5f3ca49e3d20c1a5e83917b2c8b98a7c95506 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Jul 2014 22:03:14 +0200 Subject: [PATCH 1/5] ACPI / hotplug / PCI: Eliminate acpiphp_dev_to_bridge() Since acpiphp_dev_to_bridge() is only called by acpiphp_check_host_bridge(), move the code from it to that function directly which reduces the call chain depth and makes the code slightly easier to follow. Signed-off-by: Rafael J. Wysocki Acked-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp_glue.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 602d153c7055..08043f9c1dd5 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -369,20 +369,6 @@ static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, return AE_OK; } -static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) -{ - struct acpiphp_bridge *bridge = NULL; - - acpi_lock_hp_context(); - if (adev->hp) { - bridge = to_acpiphp_root_context(adev->hp)->root_bridge; - if (bridge) - get_bridge(bridge); - } - acpi_unlock_hp_context(); - return bridge; -} - static void cleanup_bridge(struct acpiphp_bridge *bridge) { struct acpiphp_slot *slot; @@ -753,9 +739,15 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) void acpiphp_check_host_bridge(struct acpi_device *adev) { - struct acpiphp_bridge *bridge; + struct acpiphp_bridge *bridge = NULL; - bridge = acpiphp_dev_to_bridge(adev); + acpi_lock_hp_context(); + if (adev->hp) { + bridge = to_acpiphp_root_context(adev->hp)->root_bridge; + if (bridge) + get_bridge(bridge); + } + acpi_unlock_hp_context(); if (bridge) { pci_lock_rescan_remove(); From ba574dc8563c7c1d1d1c5bf3c1c99ec88513402e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Jul 2014 22:03:22 +0200 Subject: [PATCH 2/5] ACPI / hotplug: Simplify acpi_set_hp_context() Since all of the acpi_set_hp_context() callers pass at least one NULL function pointer and one caller passes NULL function pointers only to it, drop function pointer arguments from acpi_set_hp_context() and make the callers initialize the function pointers in struct acpi_hotplug_context by themselves before passing it to acpi_set_hp_context(). Signed-off-by: Rafael J. Wysocki Acked-by: Bjorn Helgaas --- drivers/acpi/scan.c | 4 +++- drivers/pci/hotplug/acpiphp_glue.c | 7 ++++--- include/acpi/acpi_bus.h | 8 +------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f775fa0d850f..3ffc9306538b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -77,7 +77,9 @@ void acpi_initialize_hp_context(struct acpi_device *adev, void (*uevent)(struct acpi_device *, u32)) { acpi_lock_hp_context(); - acpi_set_hp_context(adev, hp, notify, uevent, NULL); + hp->notify = notify; + hp->uevent = uevent; + acpi_set_hp_context(adev, hp); acpi_unlock_hp_context(); } EXPORT_SYMBOL_GPL(acpi_initialize_hp_context); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 08043f9c1dd5..24a43d4e9933 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -80,8 +80,9 @@ static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev) return NULL; context->refcount = 1; - acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL, - acpiphp_post_dock_fixup); + context->hp.notify = acpiphp_hotplug_notify; + context->hp.fixup = acpiphp_post_dock_fixup; + acpi_set_hp_context(adev, &context->hp); return context; } @@ -876,7 +877,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) goto err; root_context->root_bridge = bridge; - acpi_set_hp_context(adev, &root_context->hp, NULL, NULL, NULL); + acpi_set_hp_context(adev, &root_context->hp); } else { struct acpiphp_context *context; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index b5714580801a..e0720a569b2c 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -372,15 +372,9 @@ static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) } static inline void acpi_set_hp_context(struct acpi_device *adev, - struct acpi_hotplug_context *hp, - int (*notify)(struct acpi_device *, u32), - void (*uevent)(struct acpi_device *, u32), - void (*fixup)(struct acpi_device *)) + struct acpi_hotplug_context *hp) { hp->self = adev; - hp->notify = notify; - hp->uevent = uevent; - hp->fixup = fixup; adev->hp = hp; } From 902ee490fe841452b9665e4405d1bcd520f1ef87 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 20 Jul 2014 13:34:43 +0800 Subject: [PATCH 3/5] ACPI / hotplug / PCI: Fix sparse non static symbol warning Fixes the following sparse warning: drivers/pci/hotplug/acpiphp_glue.c:923:6: warning: symbol 'acpiphp_drop_bridge' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 24a43d4e9933..70741c8c46a0 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -920,7 +920,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) kfree(bridge); } -void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) +static void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) { if (pci_is_root_bus(bridge->pci_bus)) { struct acpiphp_root_context *root_context; From 8ab58e8e7e097bae5fe39cbc67eb93a91f7134b7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 18 Jul 2014 14:32:51 +0200 Subject: [PATCH 4/5] ACPI / video: Fix backlight taking 2 steps on a brightness up/down keypress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In various scenarious userspace will respond to brightness up/down keypresses by increasing/decreasing the backlight brightness itself. If the kernel then also changes the brightness this results in the brightness having changed 2 steps for a single keypress which is undesirable. See e.g. : https://bugs.launchpad.net/gnome-settings-daemon/+bug/527157 http://askubuntu.com/questions/173921/why-does-my-thinkpad-brightness-control-skip-steps This commit delays responding to brightness up/down keypresses by 100 ms and if userspace in that time responds by changing the backlight itself, cancels the kernels own handling of these keypresses, fixing the 2 steps issue. Link: http://marc.info/?l=linux-kernel&m=140535721100839&w=2 [hdegoede@redhat.com: Move the delayed_work struct into struct acpi_video_device instead of having it as a global] [hdegoede@redhat.com: Keep brightness_switch_enabled as a boolean and always delay the keypress handling] Tested-by: Hans de Goede Tested-by: Bjørn Mork Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 350d52a8f781..bfe1fa2fb5d1 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -204,6 +204,8 @@ struct acpi_video_device { struct acpi_video_device_flags flags; struct acpi_video_device_cap cap; struct list_head entry; + struct delayed_work switch_brightness_work; + int switch_brightness_event; struct acpi_video_bus *video; struct acpi_device *dev; struct acpi_video_device_brightness *brightness; @@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_level_current( unsigned long long *level, bool raw); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); -static int acpi_video_switch_brightness(struct acpi_video_device *device, - int event); +static void acpi_video_switch_brightness(struct work_struct *work); static bool acpi_video_use_native_backlight(void) { @@ -275,6 +276,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd) int request_level = bd->props.brightness + 2; struct acpi_video_device *vd = bl_get_data(bd); + cancel_delayed_work(&vd->switch_brightness_work); return acpi_video_device_lcd_set_level(vd, vd->brightness->levels[request_level]); } @@ -1188,6 +1190,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, data->device_id = device_id; data->video = video; data->dev = device; + INIT_DELAYED_WORK(&data->switch_brightness_work, + acpi_video_switch_brightness); attribute = acpi_video_get_device_attr(video, device_id); @@ -1410,15 +1414,18 @@ acpi_video_get_next_level(struct acpi_video_device *device, } } -static int -acpi_video_switch_brightness(struct acpi_video_device *device, int event) +static void +acpi_video_switch_brightness(struct work_struct *work) { + struct acpi_video_device *device = container_of(to_delayed_work(work), + struct acpi_video_device, switch_brightness_work); unsigned long long level_current, level_next; + int event = device->switch_brightness_event; int result = -EINVAL; /* no warning message if acpi_backlight=vendor or a quirk is used */ if (!acpi_video_verify_backlight_support()) - return 0; + return; if (!device->brightness) goto out; @@ -1440,8 +1447,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) out: if (result) printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); - - return result; } int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, @@ -1609,6 +1614,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) return; } +static void brightness_switch_event(struct acpi_video_device *video_device, + u32 event) +{ + if (!brightness_switch_enabled) + return; + + video_device->switch_brightness_event = event; + schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10); +} + static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) { struct acpi_video_device *video_device = data; @@ -1626,28 +1641,23 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESS_CYCLE; break; case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESSUP; break; case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESSDOWN; break; case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESS_ZERO; break; case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_DISPLAY_OFF; break; default: From 6d6b20b2e9498371573c3b24a3e6b4ee1343359b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Jul 2014 14:37:09 +0200 Subject: [PATCH 5/5] ACPI: move models with win8 brightness problems from win8 blacklist to use_native_backlight When the windows8 related backlight problems became evident, 2 approaches were follow in parallel, one was to stop claiming to be windows 8 / 2012, the other was to tell acpi_video to stop registering a backlight driver. I've read all the threads and it seems that which approach ended up being applied to which model laptop was never really a concious decision (AFAIK): https://bugzilla.kernel.org/show_bug.cgi?id=51231 https://bugzilla.kernel.org/show_bug.cgi?id=60682 So lets move all the models which are only on the win8 blacklist because of brightness issues to the use_native_backlight list, which is the smaller hammer to use to solve the backlight issues. Making this change is esp. attractive now that 3.16 has video.use_native_brightness=1 by default. If that new default does not get reverted because of regressions, then we can drop all the models with a use_native_backlight quirk, greatly reducing the number of models we've a quirk for. Link: https://bugzilla.kernel.org/show_bug.cgi?id=51231 Link: https://bugzilla.kernel.org/show_bug.cgi?id=60682 Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/blacklist.c | 68 ++-------------------------------------- drivers/acpi/video.c | 68 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 3d8413d02a97..36eb42e3b0bb 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -247,75 +247,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, /* - * The following machines have broken backlight support when reporting - * the Windows 2012 OSI, so disable it until their support is fixed. + * These machines will power on immediately after shutdown when + * reporting the Windows 2012 OSI. */ { .callback = dmi_disable_osi_win8, - .ident = "ASUS Zenbook Prime UX31A", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Acer Aspire V5-573G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), - DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "Acer Aspire V5-572G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), - DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad T431s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), - }, - }, - { - .callback = dmi_disable_osi_win8, - .ident = "ThinkPad T430", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), - }, - }, - { - .callback = dmi_disable_osi_win8, .ident = "Dell Inspiron 7737", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bfe1fa2fb5d1..18c0e6920eb4 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -461,6 +461,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad X230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + }, + }, { .callback = video_set_use_native_backlight, .ident = "ThinkPad T430 and T430s", @@ -471,10 +479,42 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, - .ident = "ThinkPad X230", + .ident = "ThinkPad T430", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad T431s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), }, }, { @@ -573,6 +613,30 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate B113"), }, }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-572G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-573G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ASUS Zenbook Prime UX31A", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), + }, + }, { .callback = video_set_use_native_backlight, .ident = "HP ProBook 4340s",