diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/acpica/exmutex.c | 3 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 86 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 10 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 33 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_throttling.c | 3 | ||||
-rw-r--r-- | drivers/acpi/sbs.c | 5 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 19 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 36 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 45 | ||||
-rw-r--r-- | drivers/acpi/video.c | 28 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 19 | ||||
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 91 | ||||
-rw-r--r-- | drivers/pnp/base.h | 3 | ||||
-rw-r--r-- | drivers/pnp/interface.c | 7 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/rsparser.c | 49 | ||||
-rw-r--r-- | drivers/pnp/resource.c | 27 | ||||
-rw-r--r-- | drivers/pnp/support.c | 4 | ||||
-rw-r--r-- | drivers/power/power_supply_sysfs.c | 1 |
19 files changed, 309 insertions, 162 deletions
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index cc8a10268f6..7116bc86494 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -375,8 +375,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Must have a valid thread ID */ - + /* Must have a valid thread. */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 58d2c91ba62..75f39f2c166 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -54,6 +54,7 @@ #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 #define ACPI_BATTERY_NOTIFY_INFO 0x81 +#define ACPI_BATTERY_NOTIFY_THRESHOLD 0x82 #define _COMPONENT ACPI_BATTERY_COMPONENT @@ -88,10 +89,15 @@ static const struct acpi_device_id battery_device_ids[] = { MODULE_DEVICE_TABLE(acpi, battery_device_ids); -/* For buggy DSDTs that report negative 16-bit values for either charging - * or discharging current and/or report 0 as 65536 due to bad math. - */ -#define QUIRK_SIGNED16_CURRENT 0x0001 +enum { + ACPI_BATTERY_ALARM_PRESENT, + ACPI_BATTERY_XINFO_PRESENT, + /* For buggy DSDTs that report negative 16-bit values for either + * charging or discharging current and/or report 0 as 65536 + * due to bad math. + */ + ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, +}; struct acpi_battery { struct mutex lock; @@ -109,6 +115,12 @@ struct acpi_battery { int design_voltage; int design_capacity_warning; int design_capacity_low; + int cycle_count; + int measurement_accuracy; + int max_sampling_time; + int min_sampling_time; + int max_averaging_interval; + int min_averaging_interval; int capacity_granularity_1; int capacity_granularity_2; int alarm; @@ -118,8 +130,7 @@ struct acpi_battery { char oem_info[32]; int state; int power_unit; - u8 alarm_present; - long quirks; + unsigned long flags; }; #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); @@ -198,6 +209,9 @@ static int acpi_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = acpi_battery_technology(battery); break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + val->intval = battery->cycle_count; + break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: val->intval = battery->design_voltage * 1000; break; @@ -239,6 +253,7 @@ static enum power_supply_property charge_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -254,6 +269,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -305,6 +321,28 @@ static struct acpi_offsets info_offsets[] = { {offsetof(struct acpi_battery, oem_info), 1}, }; +static struct acpi_offsets extended_info_offsets[] = { + {offsetof(struct acpi_battery, power_unit), 0}, + {offsetof(struct acpi_battery, design_capacity), 0}, + {offsetof(struct acpi_battery, full_charge_capacity), 0}, + {offsetof(struct acpi_battery, technology), 0}, + {offsetof(struct acpi_battery, design_voltage), 0}, + {offsetof(struct acpi_battery, design_capacity_warning), 0}, + {offsetof(struct acpi_battery, design_capacity_low), 0}, + {offsetof(struct acpi_battery, cycle_count), 0}, + {offsetof(struct acpi_battery, measurement_accuracy), 0}, + {offsetof(struct acpi_battery, max_sampling_time), 0}, + {offsetof(struct acpi_battery, min_sampling_time), 0}, + {offsetof(struct acpi_battery, max_averaging_interval), 0}, + {offsetof(struct acpi_battery, min_averaging_interval), 0}, + {offsetof(struct acpi_battery, capacity_granularity_1), 0}, + {offsetof(struct acpi_battery, capacity_granularity_2), 0}, + {offsetof(struct acpi_battery, model_number), 1}, + {offsetof(struct acpi_battery, serial_number), 1}, + {offsetof(struct acpi_battery, type), 1}, + {offsetof(struct acpi_battery, oem_info), 1}, +}; + static int extract_package(struct acpi_battery *battery, union acpi_object *package, struct acpi_offsets *offsets, int num) @@ -350,22 +388,29 @@ static int acpi_battery_get_info(struct acpi_battery *battery) { int result = -EFAULT; acpi_status status = 0; + char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)? + "_BIX" : "_BIF"; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; if (!acpi_battery_present(battery)) return 0; mutex_lock(&battery->lock); - status = acpi_evaluate_object(battery->device->handle, "_BIF", - NULL, &buffer); + status = acpi_evaluate_object(battery->device->handle, name, + NULL, &buffer); mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); + ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name)); return -ENODEV; } - - result = extract_package(battery, buffer.pointer, - info_offsets, ARRAY_SIZE(info_offsets)); + if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)) + result = extract_package(battery, buffer.pointer, + extended_info_offsets, + ARRAY_SIZE(extended_info_offsets)); + else + result = extract_package(battery, buffer.pointer, + info_offsets, ARRAY_SIZE(info_offsets)); kfree(buffer.pointer); return result; } @@ -399,7 +444,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->update_time = jiffies; kfree(buffer.pointer); - if ((battery->quirks & QUIRK_SIGNED16_CURRENT) && + if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) && battery->rate_now != -1) battery->rate_now = abs((s16)battery->rate_now); @@ -412,7 +457,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; struct acpi_object_list arg_list = { 1, &arg0 }; - if (!acpi_battery_present(battery)|| !battery->alarm_present) + if (!acpi_battery_present(battery) || + !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) return -ENODEV; arg0.integer.value = battery->alarm; @@ -437,10 +483,10 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) /* See if alarms are supported, and if so, set default */ status = acpi_get_handle(battery->device->handle, "_BTP", &handle); if (ACPI_FAILURE(status)) { - battery->alarm_present = 0; + clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); return 0; } - battery->alarm_present = 1; + set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); if (!battery->alarm) battery->alarm = battery->design_capacity_warning; return acpi_battery_set_alarm(battery); @@ -510,9 +556,8 @@ static void sysfs_remove_battery(struct acpi_battery *battery) static void acpi_battery_quirks(struct acpi_battery *battery) { - battery->quirks = 0; if (dmi_name_in_vendors("Acer") && battery->power_unit) { - battery->quirks |= QUIRK_SIGNED16_CURRENT; + set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags); } } @@ -590,6 +635,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) seq_printf(seq, "design capacity low: %d %sh\n", battery->design_capacity_low, acpi_battery_units(battery)); + seq_printf(seq, "cycle count: %i\n", battery->cycle_count); seq_printf(seq, "capacity granularity 1: %d %sh\n", battery->capacity_granularity_1, acpi_battery_units(battery)); @@ -841,6 +887,7 @@ static int acpi_battery_add(struct acpi_device *device) { int result = 0; struct acpi_battery *battery = NULL; + acpi_handle handle; if (!device) return -EINVAL; battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); @@ -851,6 +898,9 @@ static int acpi_battery_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); device->driver_data = battery; mutex_init(&battery->lock); + if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, + "_BIX", &handle))) + set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); acpi_battery_update(battery); #ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a52126e4630..b70cd375614 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -190,16 +190,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; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d7a6bbbb834..1ac28c6a672 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -76,8 +76,9 @@ enum ec_command { enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_STORM, /* GPE storm detected */ - EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and + EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and * OpReg are installed */ + EC_FLAGS_FROZEN, /* Transactions are suspended */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -291,6 +292,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) if (t->rdata) memset(t->rdata, 0, t->rlen); mutex_lock(&ec->lock); + if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) { + status = -EINVAL; + goto unlock; + } if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { @@ -453,6 +458,32 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); +void acpi_ec_suspend_transactions(void) +{ + struct acpi_ec *ec = first_ec; + + if (!ec) + return; + + mutex_lock(&ec->lock); + /* Prevent transactions from being carried out */ + set_bit(EC_FLAGS_FROZEN, &ec->flags); + mutex_unlock(&ec->lock); +} + +void acpi_ec_resume_transactions(void) +{ + struct acpi_ec *ec = first_ec; + + if (!ec) + return; + + mutex_lock(&ec->lock); + /* Allow transactions to be carried out again */ + clear_bit(EC_FLAGS_FROZEN, &ec->flags); + mutex_unlock(&ec->lock); +} + static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) { int result; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 9c4c962e46e..e2841136723 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -49,6 +49,8 @@ void acpi_early_processor_set_pdc(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); +void acpi_ec_suspend_transactions(void); +void acpi_ec_resume_transactions(void); /*-------------------------------------------------------------------------- Suspend/Resume diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 7ded7542fc9..29c6f5766dc 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -1133,9 +1133,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) int result = 0; struct acpi_processor_throttling *pthrottling; - if (!pr) - return -EINVAL; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", pr->throttling.address, diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index b16ddbf23a9..89ad11138e4 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -217,6 +217,9 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = acpi_battery_technology(battery); break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + val->intval = battery->cycle_count; + break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: val->intval = battery->design_voltage * acpi_battery_vscale(battery) * 1000; @@ -276,6 +279,7 @@ static enum power_supply_property sbs_charge_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, @@ -560,6 +564,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) battery->design_voltage * acpi_battery_vscale(battery)); seq_printf(seq, "design capacity warning: unknown\n"); seq_printf(seq, "design capacity low: unknown\n"); + seq_printf(seq, "cycle count: %i\n", battery->cycle_count); seq_printf(seq, "capacity granularity 1: unknown\n"); seq_printf(seq, "capacity granularity 2: unknown\n"); seq_printf(seq, "model number: %s\n", battery->device_name); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3bde594a997..f74834a544f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -552,8 +552,17 @@ static void acpi_hibernation_leave(void) hibernate_nvs_restore(); } -static void acpi_pm_enable_gpes(void) +static int acpi_pm_pre_restore(void) { + acpi_disable_all_gpes(); + acpi_os_wait_events_complete(NULL); + acpi_ec_suspend_transactions(); + return 0; +} + +static void acpi_pm_restore_cleanup(void) +{ + acpi_ec_resume_transactions(); acpi_enable_all_runtime_gpes(); } @@ -565,8 +574,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { .prepare = acpi_pm_prepare, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, - .pre_restore = acpi_pm_disable_gpes, - .restore_cleanup = acpi_pm_enable_gpes, + .pre_restore = acpi_pm_pre_restore, + .restore_cleanup = acpi_pm_restore_cleanup, }; /** @@ -618,8 +627,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { .prepare = acpi_pm_disable_gpes, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, - .pre_restore = acpi_pm_disable_gpes, - .restore_cleanup = acpi_pm_enable_gpes, + .pre_restore = acpi_pm_pre_restore, + .restore_cleanup = acpi_pm_restore_cleanup, .recover = acpi_pm_finish, }; #endif /* CONFIG_HIBERNATION */ diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 9073ada8883..5d3893558cf 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -368,7 +368,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) int valid = 0; int i; - /* Critical Shutdown (required) */ + /* Critical Shutdown */ if (flag & ACPI_TRIPS_CRITICAL) { status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); @@ -379,17 +379,19 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) * Below zero (Celsius) values clearly aren't right for sure.. * ... so lets discard those as invalid. */ - if (ACPI_FAILURE(status) || - tz->trips.critical.temperature <= 2732) { + if (ACPI_FAILURE(status)) { + tz->trips.critical.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No critical threshold\n")); + } else if (tmp <= 2732) { + printk(KERN_WARNING FW_BUG "Invalid critical threshold " + "(%llu)\n", tmp); tz->trips.critical.flags.valid = 0; - ACPI_EXCEPTION((AE_INFO, status, - "No or invalid critical threshold")); - return -ENODEV; } else { tz->trips.critical.flags.valid = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found critical threshold [%lu]\n", - tz->trips.critical.temperature)); + "Found critical threshold [%lu]\n", + tz->trips.critical.temperature)); } if (tz->trips.critical.flags.valid == 1) { if (crt == -1) { @@ -575,7 +577,23 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { - return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + + if (ret) + return ret; + + valid = tz->trips.critical.flags.valid | + tz->trips.hot.flags.valid | + tz->trips.passive.flags.valid; + + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + valid |= tz->trips.active[i].flags.valid; + + if (!valid) { + printk(KERN_WARNING FW_BUG "No valid trip found\n"); + return -ENODEV; + } + return 0; } static void acpi_thermal_check(void *data) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 11882dbe209..c9a49f4747e 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -289,51 +289,6 @@ acpi_evaluate_integer(acpi_handle handle, EXPORT_SYMBOL(acpi_evaluate_integer); -#if 0 -acpi_status -acpi_evaluate_string(acpi_handle handle, - acpi_string pathname, - acpi_object_list * arguments, acpi_string * data) -{ - acpi_status status = AE_OK; - acpi_object *element = NULL; - acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - - if (!data) - return AE_BAD_PARAMETER; - - status = acpi_evaluate_object(handle, pathname, arguments, &buffer); - if (ACPI_FAILURE(status)) { - acpi_util_eval_error(handle, pathname, status); - return status; - } - - element = (acpi_object *) buffer.pointer; - - if ((element->type != ACPI_TYPE_STRING) - || (element->type != ACPI_TYPE_BUFFER) - || !element->string.length) { - acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - return AE_BAD_DATA; - } - - *data = kzalloc(element->string.length + 1, GFP_KERNEL); - if (!data) { - printk(KERN_ERR PREFIX "Memory allocation\n"); - return -ENOMEM; - } - - memcpy(*data, element->string.pointer, element->string.length); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data)); - - kfree(buffer.pointer); - - return AE_OK; -} -#endif - acpi_status acpi_evaluate_reference(acpi_handle handle, acpi_string pathname, diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 6e9b49149fc..2ff2b6ab5b6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -327,7 +327,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); + unsigned long long *level, int init); 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, @@ -345,7 +345,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)) + if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0)) return -EINVAL; for (i = 2; i < vd->brightness->count; i++) { if (vd->brightness->levels[i] == cur_level) @@ -414,7 +414,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)) + if (acpi_video_device_lcd_get_level_current(video, &level, 0)) return -EINVAL; for (offset = 2; offset < video->brightness->count; offset++) if (level == video->brightness->levels[offset]) { @@ -609,7 +609,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = { static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, - unsigned long long *level) + unsigned long long *level, int init) { acpi_status status = AE_OK; int i; @@ -633,10 +633,16 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, device->brightness->curr = *level; return 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; + 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; + } } else { /* Fixme: * should we return an error or ignore this failure? @@ -892,7 +898,7 @@ 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); + result = acpi_video_device_lcd_get_level_current(device, &level_old, 1); if (result) goto out_free_levels; @@ -903,7 +909,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) if (result) goto out_free_levels; - result = acpi_video_device_lcd_get_level_current(device, &level); + result = acpi_video_device_lcd_get_level_current(device, &level, 0); if (result) goto out_free_levels; @@ -1996,7 +2002,7 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) goto out; result = acpi_video_device_lcd_get_level_current(device, - &level_current); + &level_current, 0); if (result) goto out; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cb2fd01edda..b5dad9f3745 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -749,6 +749,24 @@ static int acpiphp_bus_trim(acpi_handle handle) return retval; } +static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) +{ + struct acpiphp_func *func; + union acpi_object params[2]; + struct acpi_object_list arg_list; + + list_for_each_entry(func, &slot->funcs, sibling) { + arg_list.count = 2; + arg_list.pointer = params; + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = ACPI_ADR_SPACE_PCI_CONFIG; + params[1].type = ACPI_TYPE_INTEGER; + params[1].integer.value = 1; + /* _REG is optional, we don't care about if there is failure */ + acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL); + } +} + /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -805,6 +823,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); + acpiphp_set_acpi_region(slot); pci_enable_bridges(bus); pci_bus_add_devices(bus); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3f71a605a49..5a3d8514c66 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -145,7 +145,7 @@ struct sony_laptop_input_s { struct input_dev *key_dev; struct kfifo fifo; spinlock_t fifo_lock; - struct workqueue_struct *wq; + struct timer_list release_key_timer; }; static struct sony_laptop_input_s sony_laptop_input = { @@ -299,20 +299,26 @@ static int sony_laptop_input_keycode_map[] = { }; /* release buttons after a short delay if pressed */ -static void do_sony_laptop_release_key(struct work_struct *work) +static void do_sony_laptop_release_key(unsigned long unused) { struct sony_laptop_keypress kp; + unsigned long flags; + + spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags); - while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, - sizeof(kp), &sony_laptop_input.fifo_lock) - == sizeof(kp)) { - msleep(10); + if (kfifo_out(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); } + + /* If there is something in the fifo schedule next release. */ + if (kfifo_len(&sony_laptop_input.fifo) != 0) + mod_timer(&sony_laptop_input.release_key_timer, + jiffies + msecs_to_jiffies(10)); + + spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags); } -static DECLARE_WORK(sony_laptop_release_key_work, - do_sony_laptop_release_key); /* forward event to the input subsystem */ static void sony_laptop_report_input_event(u8 event) @@ -366,13 +372,13 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_in_locked(&sony_laptop_input.fifo, - (unsigned char *)&kp, sizeof(kp), - &sony_laptop_input.fifo_lock); - if (!work_pending(&sony_laptop_release_key_work)) - queue_work(sony_laptop_input.wq, - &sony_laptop_release_key_work); + /* schedule key release */ + kfifo_in_locked(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp), + &sony_laptop_input.fifo_lock); + mod_timer(&sony_laptop_input.release_key_timer, + jiffies + msecs_to_jiffies(10)); } else dprintk("unknown input event %.2x\n", event); } @@ -390,27 +396,21 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) /* kfifo */ spin_lock_init(&sony_laptop_input.fifo_lock); - error = - kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); + error = kfifo_alloc(&sony_laptop_input.fifo, + SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); goto err_dec_users; } - /* init workqueue */ - sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); - if (!sony_laptop_input.wq) { - printk(KERN_ERR DRV_PFX - "Unable to create workqueue.\n"); - error = -ENXIO; - goto err_free_kfifo; - } + setup_timer(&sony_laptop_input.release_key_timer, + do_sony_laptop_release_key, 0); /* input keys */ key_dev = input_allocate_device(); if (!key_dev) { error = -ENOMEM; - goto err_destroy_wq; + goto err_free_kfifo; } key_dev->name = "Sony Vaio Keys"; @@ -419,18 +419,15 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) key_dev->dev.parent = &acpi_device->dev; /* Initialize the Input Drivers: special keys */ - set_bit(EV_KEY, key_dev->evbit); - set_bit(EV_MSC, key_dev->evbit); - set_bit(MSC_SCAN, key_dev->mscbit); + input_set_capability(key_dev, EV_MSC, MSC_SCAN); + + __set_bit(EV_KEY, key_dev->evbit); key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); key_dev->keycode = &sony_laptop_input_keycode_map; - for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { - if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { - set_bit(sony_laptop_input_keycode_map[i], - key_dev->keybit); - } - } + for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) + __set_bit(sony_laptop_input_keycode_map[i], key_dev->keybit); + __clear_bit(KEY_RESERVED, key_dev->keybit); error = input_register_device(key_dev); if (error) @@ -450,9 +447,8 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) jog_dev->id.vendor = PCI_VENDOR_ID_SONY; key_dev->dev.parent = &acpi_device->dev; - jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); - jog_dev->relbit[0] = BIT_MASK(REL_WHEEL); + input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE); + input_set_capability(jog_dev, EV_REL, REL_WHEEL); error = input_register_device(jog_dev); if (error) @@ -473,9 +469,6 @@ err_unregister_keydev: err_free_keydev: input_free_device(key_dev); -err_destroy_wq: - destroy_workqueue(sony_laptop_input.wq); - err_free_kfifo: kfifo_free(&sony_laptop_input.fifo); @@ -486,12 +479,23 @@ err_dec_users: static void sony_laptop_remove_input(void) { - /* cleanup only after the last user has gone */ + struct sony_laptop_keypress kp = { NULL }; + + /* Cleanup only after the last user has gone */ if (!atomic_dec_and_test(&sony_laptop_input.users)) return; - /* flush workqueue first */ - flush_workqueue(sony_laptop_input.wq); + del_timer_sync(&sony_laptop_input.release_key_timer); + + /* + * Generate key-up events for remaining keys. Note that we don't + * need locking since nobody is adding new events to the kfifo. + */ + while (kfifo_out(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { + input_report_key(kp.dev, kp.key, 0); + input_sync(kp.dev); + } /* destroy input devs */ input_unregister_device(sony_laptop_input.key_dev); @@ -502,7 +506,6 @@ static void sony_laptop_remove_input(void) sony_laptop_input.jog_dev = NULL; } - destroy_workqueue(sony_laptop_input.wq); kfifo_free(&sony_laptop_input.fifo); } diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 0b8d14050ef..0bab84ebb15 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -166,6 +166,9 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, resource_size_t start, resource_size_t end, int flags); +struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev, + resource_size_t start, + resource_size_t end); extern int pnp_debug; diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 68b0c04987e..cfaf5b73540 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -278,9 +278,12 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, switch (pnp_resource_type(res)) { case IORESOURCE_IO: case IORESOURCE_MEM: - pnp_printf(buffer, " %#llx-%#llx\n", + case IORESOURCE_BUS: + pnp_printf(buffer, " %#llx-%#llx%s\n", (unsigned long long) res->start, - (unsigned long long) res->end); + (unsigned long long) res->end, + res->flags & IORESOURCE_WINDOW ? + " window" : ""); break; case IORESOURCE_IRQ: case IORESOURCE_DMA: diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 5702b2c8691..54514aa35b0 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -177,7 +177,8 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master, } static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, - u64 len, int io_decode) + u64 len, int io_decode, + int window) { int flags = 0; u64 end = start + len - 1; @@ -186,6 +187,8 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, flags |= IORESOURCE_IO_16BIT_ADDR; if (len == 0 || end >= 0x10003) flags |= IORESOURCE_DISABLED; + if (window) + flags |= IORESOURCE_WINDOW; pnp_add_io_resource(dev, start, end, flags); } @@ -247,7 +250,7 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev, static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, u64 start, u64 len, - int write_protect) + int write_protect, int window) { int flags = 0; u64 end = start + len - 1; @@ -256,15 +259,26 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, flags |= IORESOURCE_DISABLED; if (write_protect == ACPI_READ_WRITE_MEMORY) flags |= IORESOURCE_MEM_WRITEABLE; + if (window) + flags |= IORESOURCE_WINDOW; pnp_add_mem_resource(dev, start, end, flags); } +static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev, + u64 start, u64 len) +{ + u64 end = start + len - 1; + + pnp_add_bus_resource(dev, start, end); +} + static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, struct acpi_resource *res) { struct acpi_resource_address64 addr, *p = &addr; acpi_status status; + int window; status = acpi_resource_to_address64(res, p); if (!ACPI_SUCCESS(status)) { @@ -273,37 +287,42 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, return; } - if (p->producer_consumer == ACPI_PRODUCER) - return; + window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(dev, p->minimum, p->address_length, - p->info.mem.write_protect); + p->info.mem.write_protect, window); else if (p->resource_type == ACPI_IO_RANGE) pnpacpi_parse_allocated_ioresource(dev, p->minimum, p->address_length, p->granularity == 0xfff ? ACPI_DECODE_10 : - ACPI_DECODE_16); + ACPI_DECODE_16, window); + else if (p->resource_type == ACPI_BUS_NUMBER_RANGE) + pnpacpi_parse_allocated_busresource(dev, p->minimum, + p->address_length); } static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, struct acpi_resource *res) { struct acpi_resource_extended_address64 *p = &res->data.ext_address64; + int window; - if (p->producer_consumer == ACPI_PRODUCER) - return; + window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(dev, p->minimum, p->address_length, - p->info.mem.write_protect); + p->info.mem.write_protect, window); else if (p->resource_type == ACPI_IO_RANGE) pnpacpi_parse_allocated_ioresource(dev, p->minimum, p->address_length, p->granularity == 0xfff ? ACPI_DECODE_10 : - ACPI_DECODE_16); + ACPI_DECODE_16, window); + else if (p->resource_type == ACPI_BUS_NUMBER_RANGE) + pnpacpi_parse_allocated_busresource(dev, p->minimum, + p->address_length); } static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, @@ -368,7 +387,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, pnpacpi_parse_allocated_ioresource(dev, io->minimum, io->address_length, - io->io_decode); + io->io_decode, 0); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -380,7 +399,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, pnpacpi_parse_allocated_ioresource(dev, fixed_io->address, fixed_io->address_length, - ACPI_DECODE_10); + ACPI_DECODE_10, 0); break; case ACPI_RESOURCE_TYPE_VENDOR: @@ -396,21 +415,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, pnpacpi_parse_allocated_memresource(dev, memory24->minimum, memory24->address_length, - memory24->write_protect); + memory24->write_protect, 0); break; case ACPI_RESOURCE_TYPE_MEMORY32: memory32 = &res->data.memory32; pnpacpi_parse_allocated_memresource(dev, memory32->minimum, memory32->address_length, - memory32->write_protect); + memory32->write_protect, 0); break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: fixed_memory32 = &res->data.fixed_memory32; pnpacpi_parse_allocated_memresource(dev, fixed_memory32->address, fixed_memory32->address_length, - fixed_memory32->write_protect); + fixed_memory32->write_protect, 0); break; case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 64d0596bafb..5b277dbaacd 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -470,7 +470,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res) unsigned long pnp_resource_type(struct resource *res) { return res->flags & (IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_IRQ | IORESOURCE_DMA); + IORESOURCE_IRQ | IORESOURCE_DMA | + IORESOURCE_BUS); } struct resource *pnp_get_resource(struct pnp_dev *dev, @@ -590,6 +591,30 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, return pnp_res; } +struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev, + resource_size_t start, + resource_size_t end) +{ + struct pnp_resource *pnp_res; + struct resource *res; + + pnp_res = pnp_new_resource(dev); + if (!pnp_res) { + dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n", + (unsigned long long) start, + (unsigned long long) end); + return NULL; + } + + res = &pnp_res->res; + res->flags = IORESOURCE_BUS; + res->start = start; + res->end = end; + + pnp_dbg(&dev->dev, " add %pr\n", res); + return pnp_res; +} + /* * Determine whether the specified resource is a possible configuration * for this device. diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 9585c1c1cc3..f5beb24d036 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -69,8 +69,10 @@ char *pnp_resource_type_name(struct resource *res) return "irq"; case IORESOURCE_DMA: return "dma"; + case IORESOURCE_BUS: + return "bus"; } - return NULL; + return "unknown"; } void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index c790e0c77d4..ff05e618976 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -99,6 +99,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(present), POWER_SUPPLY_ATTR(online), POWER_SUPPLY_ATTR(technology), + POWER_SUPPLY_ATTR(cycle_count), POWER_SUPPLY_ATTR(voltage_max), POWER_SUPPLY_ATTR(voltage_min), POWER_SUPPLY_ATTR(voltage_max_design), |