diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-28 01:54:08 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-28 01:54:08 +0200 |
commit | c940c8ce1db3ed3909d31c02aef01a864565519c (patch) | |
tree | 725597abd9bd910792410ddfe89cc0857d7667b2 /drivers/acpi | |
parent | 34bdb1a458baaf3e56843c36deb04283c26a8099 (diff) | |
parent | 94a409319561ec1847fd9bf996a2d5843ad00932 (diff) | |
download | talos-op-linux-c940c8ce1db3ed3909d31c02aef01a864565519c.tar.gz talos-op-linux-c940c8ce1db3ed3909d31c02aef01a864565519c.zip |
Merge branch 'acpi-assorted'
* acpi-assorted: (21 commits)
ACPI / thermal: do not always return THERMAL_TREND_RAISING for active trip points
ACPI: video: correct acpi_video_bus_add error processing
ACPI: Fix wrong parameter passed to memblock_reserve
acpi: video: enhance the quirk detect logic of _BQC
ACPI: update comments for acpi_event_status
ACPI: remove "config ACPI_DEBUG_FUNC_TRACE"
PCI / ACPI: Don't query OSC support with all possible controls
ACPI / processor_thermal: avoid null pointer deference error
ACPI / fan: avoid null pointer deference error
ACPI / video: Fix applying indexed initial brightness value.
ACPI / video: Make logic a little easier to understand.
ACPI / video: Fix brightness control initialization for some laptops.
ACPI: Use resource_size() in osl.c
ACPI / acpi_pad: Used PTR_RET
ACPI: suppress compiler warning in container.c
ACPI: suppress compiler warning in battery.c
ACPI: suppress compiler warnings in processor_throttling.c
ACPI: suppress compiler warnings in button.c
ACPI: replace kmalloc+memcpy with kmemdup
ACPI: Remove acpi_pci_bind_root() definition
...
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/acpi/acpi_pad.c | 2 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 5 | ||||
-rw-r--r-- | drivers/acpi/button.c | 1 | ||||
-rw-r--r-- | drivers/acpi/container.c | 2 | ||||
-rw-r--r-- | drivers/acpi/fan.c | 8 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 4 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 4 | ||||
-rw-r--r-- | drivers/acpi/processor_thermal.c | 24 | ||||
-rw-r--r-- | drivers/acpi/processor_throttling.c | 3 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 16 | ||||
-rw-r--r-- | drivers/acpi/video.c | 318 |
13 files changed, 243 insertions, 154 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8fcae6df0a42..100bd724f648 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -298,14 +298,6 @@ config ACPI_DEBUG Documentation/kernel-parameters.txt to control the type and amount of debug output. -config ACPI_DEBUG_FUNC_TRACE - bool "Additionally enable ACPI function tracing" - default n - depends on ACPI_DEBUG - help - ACPI Debug Statements slow down ACPI processing. Function trace - is about half of the penalty and is rarely useful. - config ACPI_PCI_SLOT bool "PCI slot detection driver" depends on SYSFS diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 31de1043eea0..27bb6a91de5f 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -236,7 +236,7 @@ static int create_power_saving_task(void) ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, (void *)(unsigned long)ps_tsk_num, "acpi_pad/%d", ps_tsk_num); - rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; + rc = PTR_RET(ps_tsks[ps_tsk_num]); if (!rc) ps_tsk_num++; else diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c5cd5b5513e6..0cc384b72943 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -146,7 +146,7 @@ struct acpi_battery { #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat) -inline int acpi_battery_present(struct acpi_battery *battery) +static inline int acpi_battery_present(struct acpi_battery *battery) { return battery->device->status.battery_present; } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 01708a165368..292de3cab9cc 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -288,13 +288,12 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) } out_success: context->ret.length = out_obj->buffer.length; - context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); + context->ret.pointer = kmemdup(out_obj->buffer.pointer, + context->ret.length, GFP_KERNEL); if (!context->ret.pointer) { status = AE_NO_MEMORY; goto out_kfree; } - memcpy(context->ret.pointer, out_obj->buffer.pointer, - context->ret.length); status = AE_OK; out_kfree: diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 86c7d5445c38..92a659aa6396 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -33,6 +33,7 @@ #include <linux/slab.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> +#include <acpi/button.h> #define PREFIX "ACPI: " diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index f9f8a08827fa..e23151667655 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -30,6 +30,8 @@ #include "internal.h" +#include "internal.h" + #define PREFIX "ACPI: " #define _COMPONENT ACPI_CONTAINER_COMPONENT diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index f815da82c765..8d1c0105e113 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -174,9 +174,13 @@ static int acpi_fan_add(struct acpi_device *device) static int acpi_fan_remove(struct acpi_device *device) { - struct thermal_cooling_device *cdev = acpi_driver_data(device); + struct thermal_cooling_device *cdev; + + if (!device) + return -EINVAL; - if (!device || !cdev) + cdev = acpi_driver_data(device); + if (!cdev) return -EINVAL; sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 586e7e993d3d..e72186340fec 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -641,7 +641,7 @@ void __init acpi_initrd_override(void *data, size_t size) * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) * works fine. */ - memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size); + memblock_reserve(acpi_tables_addr, all_tables_size); arch_reserve_mem_area(acpi_tables_addr, all_tables_size); p = early_ioremap(acpi_tables_addr, all_tables_size); @@ -1555,7 +1555,7 @@ int acpi_check_resource_conflict(const struct resource *res) else space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; - length = res->end - res->start + 1; + length = resource_size(res); if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) warn = 1; clash = acpi_check_address_range(space_id, res->start, length, warn); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 6ae5e440436e..4241b8d844eb 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -201,8 +201,8 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, *control &= OSC_PCI_CONTROL_MASKS; capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; } else { - /* Run _OSC query for all possible controls. */ - capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + /* Run _OSC query only with existing controls. */ + capbuf[OSC_CONTROL_TYPE] = root->osc_control_set; } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 641b5450a0db..e8e652710e65 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -218,9 +218,13 @@ processor_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state) { struct acpi_device *device = cdev->devdata; - struct acpi_processor *pr = acpi_driver_data(device); + struct acpi_processor *pr; - if (!device || !pr) + if (!device) + return -EINVAL; + + pr = acpi_driver_data(device); + if (!pr) return -EINVAL; *state = acpi_processor_max_state(pr); @@ -232,9 +236,13 @@ processor_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *cur_state) { struct acpi_device *device = cdev->devdata; - struct acpi_processor *pr = acpi_driver_data(device); + struct acpi_processor *pr; - if (!device || !pr) + if (!device) + return -EINVAL; + + pr = acpi_driver_data(device); + if (!pr) return -EINVAL; *cur_state = cpufreq_get_cur_state(pr->id); @@ -248,11 +256,15 @@ processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct acpi_device *device = cdev->devdata; - struct acpi_processor *pr = acpi_driver_data(device); + struct acpi_processor *pr; int result = 0; int max_pstate; - if (!device || !pr) + if (!device) + return -EINVAL; + + pr = acpi_driver_data(device); + if (!pr) return -EINVAL; max_pstate = cpufreq_get_max_state(pr->id); diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 1d02b7b5ade0..e7dd2c1fee79 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -211,9 +211,10 @@ err_ret: */ void acpi_processor_throttling_init(void) { - if (acpi_processor_update_tsd_coord()) + if (acpi_processor_update_tsd_coord()) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assume no T-state coordination\n")); + } return; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 8470771e5eae..a33821ca3895 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -723,9 +723,19 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, return -EINVAL; if (type == THERMAL_TRIP_ACTIVE) { - /* aggressive active cooling */ - *trend = THERMAL_TREND_RAISING; - return 0; + unsigned long trip_temp; + unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature, + tz->kelvin_offset); + if (thermal_get_trip_temp(thermal, trip, &trip_temp)) + return -EINVAL; + + if (temp > trip_temp) { + *trend = THERMAL_TREND_RAISING; + return 0; + } else { + /* Fall back on default trend */ + return -EINVAL; + } } /* diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 313f959413dc..c3932d0876e0 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -167,7 +167,8 @@ struct acpi_video_device_flags { u8 dvi:1; u8 bios:1; u8 unknown:1; - u8 reserved:2; + u8 notify:1; + u8 reserved:1; }; struct acpi_video_device_cap { @@ -222,7 +223,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level); static int acpi_video_device_lcd_get_level_current( struct acpi_video_device *device, - unsigned long long *level, int init); + 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, @@ -236,7 +237,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd) struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0)) + if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false)) return -EINVAL; for (i = 2; i < vd->brightness->count; i++) { if (vd->brightness->levels[i] == cur_level) @@ -281,7 +282,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig unsigned long long level; int offset; - if (acpi_video_device_lcd_get_level_current(video, &level, 0)) + if (acpi_video_device_lcd_get_level_current(video, &level, false)) return -EINVAL; for (offset = 2; offset < video->brightness->count; offset++) if (level == video->brightness->levels[offset]) { @@ -447,12 +448,45 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP Pavilion dm4", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"), + }, + }, {} }; +static unsigned long long +acpi_video_bqc_value_to_level(struct acpi_video_device *device, + unsigned long long bqc_value) +{ + unsigned long long level; + + if (device->brightness->flags._BQC_use_index) { + /* + * _BQC returns an index that doesn't account for + * the first 2 items with special meaning, so we need + * to compensate for that by offsetting ourselves + */ + if (device->brightness->flags._BCL_reversed) + bqc_value = device->brightness->count - 3 - bqc_value; + + level = device->brightness->levels[bqc_value + 2]; + } else { + level = bqc_value; + } + + level += bqc_offset_aml_bug_workaround; + + return level; +} + static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, - unsigned long long *level, int init) + unsigned long long *level, bool raw) { acpi_status status = AE_OK; int i; @@ -463,29 +497,30 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, status = acpi_evaluate_integer(device->dev->handle, buf, NULL, level); if (ACPI_SUCCESS(status)) { - if (device->brightness->flags._BQC_use_index) { - if (device->brightness->flags._BCL_reversed) - *level = device->brightness->count - - 3 - (*level); - *level = device->brightness->levels[*level + 2]; - + if (raw) { + /* + * Caller has indicated he wants the raw + * value returned by _BQC, so don't furtherly + * mess with the value. + */ + return 0; } - *level += bqc_offset_aml_bug_workaround; + + *level = acpi_video_bqc_value_to_level(device, *level); + for (i = 2; i < device->brightness->count; i++) if (device->brightness->levels[i] == *level) { device->brightness->curr = *level; return 0; } - if (!init) { - /* - * BQC returned an invalid level. - * Stop using it. - */ - ACPI_WARNING((AE_INFO, - "%s returned an invalid level", - buf)); - device->cap._BQC = device->cap._BCQ = 0; - } + /* + * BQC returned an invalid level. + * Stop using it. + */ + ACPI_WARNING((AE_INFO, + "%s returned an invalid level", + buf)); + device->cap._BQC = device->cap._BCQ = 0; } else { /* Fixme: * should we return an error or ignore this failure? @@ -598,6 +633,56 @@ acpi_video_cmp_level(const void *a, const void *b) } /* + * Decides if _BQC/_BCQ for this system is usable + * + * We do this by changing the level first and then read out the current + * brightness level, if the value does not match, find out if it is using + * index. If not, clear the _BQC/_BCQ capability. + */ +static int acpi_video_bqc_quirk(struct acpi_video_device *device, + int max_level, int current_level) +{ + struct acpi_video_device_brightness *br = device->brightness; + int result; + unsigned long long level; + int test_level; + + /* don't mess with existing known broken systems */ + if (bqc_offset_aml_bug_workaround) + return 0; + + /* + * Some systems always report current brightness level as maximum + * through _BQC, we need to test another value for them. + */ + test_level = current_level == max_level ? br->levels[2] : max_level; + + result = acpi_video_device_lcd_set_level(device, test_level); + if (result) + return result; + + result = acpi_video_device_lcd_get_level_current(device, &level, true); + if (result) + return result; + + if (level != test_level) { + /* buggy _BQC found, need to find out if it uses index */ + if (level < br->count) { + if (br->flags._BCL_reversed) + level = br->count - 3 - level; + if (br->levels[level + 2] == test_level) + br->flags._BQC_use_index = 1; + } + + if (!br->flags._BQC_use_index) + device->cap._BQC = device->cap._BCQ = 0; + } + + return 0; +} + + +/* * Arg: * device : video output device (LCD, CRT, ..) * @@ -703,42 +788,36 @@ acpi_video_init_brightness(struct acpi_video_device *device) if (!device->cap._BQC) goto set_level; - result = acpi_video_device_lcd_get_level_current(device, &level_old, 1); - if (result) - goto out_free_levels; - - /* - * Set the level to maximum and check if _BQC uses indexed value - */ - result = acpi_video_device_lcd_set_level(device, max_level); + result = acpi_video_device_lcd_get_level_current(device, + &level_old, true); if (result) goto out_free_levels; - result = acpi_video_device_lcd_get_level_current(device, &level, 0); + result = acpi_video_bqc_quirk(device, max_level, level_old); if (result) goto out_free_levels; + /* + * cap._BQC may get cleared due to _BQC is found to be broken + * in acpi_video_bqc_quirk, so check again here. + */ + if (!device->cap._BQC) + goto set_level; - br->flags._BQC_use_index = (level == max_level ? 0 : 1); - - if (!br->flags._BQC_use_index) { + if (use_bios_initial_backlight) { + level = acpi_video_bqc_value_to_level(device, level_old); /* - * Set the backlight to the initial state. - * On some buggy laptops, _BQC returns an uninitialized value - * when invoked for the first time, i.e. level_old is invalid. - * set the backlight to max_level in this case + * On some buggy laptops, _BQC returns an uninitialized + * value when invoked for the first time, i.e. + * level_old is invalid (no matter whether it's a level + * or an index). Set the backlight to max_level in this case. */ - if (use_bios_initial_backlight) { - for (i = 2; i < br->count; i++) - if (level_old == br->levels[i]) - level = level_old; - } - goto set_level; + for (i = 2; i < br->count; i++) + if (level_old == br->levels[i]) + break; + if (i == br->count) + level = max_level; } - if (br->flags._BCL_reversed) - level_old = (br->count - 1) - level_old; - level = br->levels[level_old]; - set_level: result = acpi_video_device_lcd_set_level(device, level); if (result) @@ -996,53 +1075,51 @@ acpi_video_bus_get_one_device(struct acpi_device *device, struct acpi_video_device *data; struct acpi_video_device_attrib* attribute; - if (!device || !video) - return -EINVAL; - status = acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); - if (ACPI_SUCCESS(status)) { - - data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); - if (!data) - return -ENOMEM; - - strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); - device->driver_data = data; - - data->device_id = device_id; - data->video = video; - data->dev = device; + /* Some device omits _ADR, we skip them instead of fail */ + if (ACPI_FAILURE(status)) + return 0; - attribute = acpi_video_get_device_attr(video, device_id); + data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); + if (!data) + return -ENOMEM; - if((attribute != NULL) && attribute->device_id_scheme) { - switch (attribute->display_type) { - case ACPI_VIDEO_DISPLAY_CRT: - data->flags.crt = 1; - break; - case ACPI_VIDEO_DISPLAY_TV: - data->flags.tvout = 1; - break; - case ACPI_VIDEO_DISPLAY_DVI: - data->flags.dvi = 1; - break; - case ACPI_VIDEO_DISPLAY_LCD: - data->flags.lcd = 1; - break; - default: - data->flags.unknown = 1; - break; - } - if(attribute->bios_can_detect) - data->flags.bios = 1; - } else { - /* Check for legacy IDs */ - device_type = acpi_video_get_device_type(video, - device_id); - /* Ignore bits 16 and 18-20 */ - switch (device_type & 0xffe2ffff) { + strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); + device->driver_data = data; + + data->device_id = device_id; + data->video = video; + data->dev = device; + + attribute = acpi_video_get_device_attr(video, device_id); + + if((attribute != NULL) && attribute->device_id_scheme) { + switch (attribute->display_type) { + case ACPI_VIDEO_DISPLAY_CRT: + data->flags.crt = 1; + break; + case ACPI_VIDEO_DISPLAY_TV: + data->flags.tvout = 1; + break; + case ACPI_VIDEO_DISPLAY_DVI: + data->flags.dvi = 1; + break; + case ACPI_VIDEO_DISPLAY_LCD: + data->flags.lcd = 1; + break; + default: + data->flags.unknown = 1; + break; + } + if(attribute->bios_can_detect) + data->flags.bios = 1; + } else { + /* Check for legacy IDs */ + device_type = acpi_video_get_device_type(video, device_id); + /* Ignore bits 16 and 18-20 */ + switch (device_type & 0xffe2ffff) { case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: data->flags.crt = 1; break; @@ -1054,34 +1131,24 @@ acpi_video_bus_get_one_device(struct acpi_device *device, break; default: data->flags.unknown = 1; - } } + } - acpi_video_device_bind(video, data); - acpi_video_device_find_cap(data); - - status = acpi_install_notify_handler(device->handle, - ACPI_DEVICE_NOTIFY, - acpi_video_device_notify, - data); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Error installing notify handler\n"); - if(data->brightness) - kfree(data->brightness->levels); - kfree(data->brightness); - kfree(data); - return -ENODEV; - } + acpi_video_device_bind(video, data); + acpi_video_device_find_cap(data); - mutex_lock(&video->device_list_lock); - list_add_tail(&data->entry, &video->video_device_list); - mutex_unlock(&video->device_list_lock); + status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_video_device_notify, data); + if (ACPI_FAILURE(status)) + dev_err(&device->dev, "Error installing notify handler\n"); + else + data->flags.notify = 1; - return 0; - } + mutex_lock(&video->device_list_lock); + list_add_tail(&data->entry, &video->video_device_list); + mutex_unlock(&video->device_list_lock); - return -ENOENT; + return status; } /* @@ -1268,7 +1335,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) goto out; result = acpi_video_device_lcd_get_level_current(device, - &level_current, 0); + &level_current, + false); if (result) goto out; @@ -1373,9 +1441,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, status = acpi_video_bus_get_one_device(dev, video); if (status) { - printk(KERN_WARNING PREFIX - "Can't attach device\n"); - continue; + dev_err(&dev->dev, "Can't attach device\n"); + break; } } return status; @@ -1388,13 +1455,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) if (!device || !device->video) return -ENOENT; - status = acpi_remove_notify_handler(device->dev->handle, - ACPI_DEVICE_NOTIFY, - acpi_video_device_notify); - if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PREFIX - "Can't remove video notify handler\n"); + if (device->flags.notify) { + status = acpi_remove_notify_handler(device->dev->handle, + ACPI_DEVICE_NOTIFY, acpi_video_device_notify); + if (ACPI_FAILURE(status)) + dev_err(&device->dev->dev, + "Can't remove video notify handler\n"); } + if (device->backlight) { backlight_device_unregister(device->backlight); device->backlight = NULL; @@ -1676,7 +1744,7 @@ static int acpi_video_bus_add(struct acpi_device *device) error = acpi_video_bus_get_devices(video, device); if (error) - goto err_free_video; + goto err_put_video; video->input = input = input_allocate_device(); if (!input) { |