diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-25 18:25:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-25 18:25:52 -0400 |
| commit | f4cb707e7ad9727a046b463232f2de166e327d3e (patch) | |
| tree | cd61b4cc816974878ccc6ba2f4c185e01836c20c | |
| parent | 12df9f376d895011fb667980c8e204e050122772 (diff) | |
| parent | 381e63da44301f49be5876d56a5da2434f132dff (diff) | |
Merge tag 'pm+acpi-3.17-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
"These are regression fixes (ACPI hotplug, cpufreq, hibernation, ACPI
LPSS driver), fixes for stuff that never worked correctly (ACPI GPIO
support in some cases and a wrong sign of an error code in the ACPI
core in one place), and one blacklist item for ACPI backlight
handling.
Specifics:
- Revert of a recent hibernation core commit that introduced a NULL
pointer dereference during resume for at least one user (Rafael J
Wysocki).
- Fix for the ACPI LPSS (Low-Power Subsystem) driver to disable
asynchronous PM callback execution for LPSS devices during system
suspend/resume (introduced in 3.16) which turns out to break
ordering expectations on some systems. From Fu Zhonghui.
- cpufreq core fix related to the handling of sysfs nodes during
system suspend/resume that has been broken for intel_pstate since
3.15 from Lan Tianyu.
- Restore the generation of "online" uevents for ACPI container
devices that was removed in 3.14, but some user space utilities
turn out to need them (Rafael J Wysocki).
- The cpufreq core fails to release a lock in an error code path
after changes made in 3.14. Fix from Prarit Bhargava.
- ACPICA and ACPI/GPIO fixes to make the handling of ACPI GPIO
operation regions (which means AML using GPIOs) work correctly in
all cases from Bob Moore and Srinivas Pandruvada.
- Fix for a wrong sign of the ACPI core's create_modalias() return
value in case of an error from Mika Westerberg.
- ACPI backlight blacklist entry for ThinkPad X201s from Aaron Lu"
* tag 'pm+acpi-3.17-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
Revert "PM / Hibernate: Iterate over set bits instead of PFNs in swsusp_free()"
gpio / ACPI: Use pin index and bit length
ACPICA: Update to GPIO region handler interface.
ACPI / platform / LPSS: disable async suspend/resume of LPSS devices
cpufreq: release policy->rwsem on error
cpufreq: fix cpufreq suspend/resume for intel_pstate
ACPI / scan: Correct error return value of create_modalias()
ACPI / video: disable native backlight for ThinkPad X201s
ACPI / hotplug: Generate online uevents for ACPI containers
| -rw-r--r-- | drivers/acpi/acpi_lpss.c | 1 | ||||
| -rw-r--r-- | drivers/acpi/acpica/aclocal.h | 1 | ||||
| -rw-r--r-- | drivers/acpi/acpica/acobject.h | 1 | ||||
| -rw-r--r-- | drivers/acpi/acpica/dsfield.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/acpica/evregion.c | 47 | ||||
| -rw-r--r-- | drivers/acpi/acpica/exfield.c | 67 | ||||
| -rw-r--r-- | drivers/acpi/acpica/exprep.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/container.c | 8 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 5 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 8 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 10 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 5 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 1 | ||||
| -rw-r--r-- | kernel/power/snapshot.c | 50 |
14 files changed, 150 insertions, 58 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index fddc1e86f9d0..b0ea767c8696 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
| @@ -419,7 +419,6 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
| 419 | adev->driver_data = pdata; | 419 | adev->driver_data = pdata; |
| 420 | pdev = acpi_create_platform_device(adev); | 420 | pdev = acpi_create_platform_device(adev); |
| 421 | if (!IS_ERR_OR_NULL(pdev)) { | 421 | if (!IS_ERR_OR_NULL(pdev)) { |
| 422 | device_enable_async_suspend(&pdev->dev); | ||
| 423 | return 1; | 422 | return 1; |
| 424 | } | 423 | } |
| 425 | 424 | ||
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 1f9aba5fb81f..2747279fbe3c 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
| @@ -254,6 +254,7 @@ struct acpi_create_field_info { | |||
| 254 | u32 field_bit_position; | 254 | u32 field_bit_position; |
| 255 | u32 field_bit_length; | 255 | u32 field_bit_length; |
| 256 | u16 resource_length; | 256 | u16 resource_length; |
| 257 | u16 pin_number_index; | ||
| 257 | u8 field_flags; | 258 | u8 field_flags; |
| 258 | u8 attribute; | 259 | u8 attribute; |
| 259 | u8 field_type; | 260 | u8 field_type; |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 22fb6449d3d6..8abb393dafab 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
| @@ -264,6 +264,7 @@ struct acpi_object_region_field { | |||
| 264 | ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; | 264 | ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; |
| 265 | union acpi_operand_object *region_obj; /* Containing op_region object */ | 265 | union acpi_operand_object *region_obj; /* Containing op_region object */ |
| 266 | u8 *resource_buffer; /* resource_template for serial regions/fields */ | 266 | u8 *resource_buffer; /* resource_template for serial regions/fields */ |
| 267 | u16 pin_number_index; /* Index relative to previous Connection/Template */ | ||
| 267 | }; | 268 | }; |
| 268 | 269 | ||
| 269 | struct acpi_object_bank_field { | 270 | struct acpi_object_bank_field { |
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 3661c8e90540..c57666196672 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c | |||
| @@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, | |||
| 360 | */ | 360 | */ |
| 361 | info->resource_buffer = NULL; | 361 | info->resource_buffer = NULL; |
| 362 | info->connection_node = NULL; | 362 | info->connection_node = NULL; |
| 363 | info->pin_number_index = 0; | ||
| 363 | 364 | ||
| 364 | /* | 365 | /* |
| 365 | * A Connection() is either an actual resource descriptor (buffer) | 366 | * A Connection() is either an actual resource descriptor (buffer) |
| @@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, | |||
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | info->field_bit_position += info->field_bit_length; | 440 | info->field_bit_position += info->field_bit_length; |
| 441 | info->pin_number_index++; /* Index relative to previous Connection() */ | ||
| 440 | break; | 442 | break; |
| 441 | 443 | ||
| 442 | default: | 444 | default: |
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 9957297d1580..8eb8575e8c16 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c | |||
| @@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
| 142 | union acpi_operand_object *region_obj2; | 142 | union acpi_operand_object *region_obj2; |
| 143 | void *region_context = NULL; | 143 | void *region_context = NULL; |
| 144 | struct acpi_connection_info *context; | 144 | struct acpi_connection_info *context; |
| 145 | acpi_physical_address address; | ||
| 145 | 146 | ||
| 146 | ACPI_FUNCTION_TRACE(ev_address_space_dispatch); | 147 | ACPI_FUNCTION_TRACE(ev_address_space_dispatch); |
| 147 | 148 | ||
| @@ -231,25 +232,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
| 231 | /* We have everything we need, we can invoke the address space handler */ | 232 | /* We have everything we need, we can invoke the address space handler */ |
| 232 | 233 | ||
| 233 | handler = handler_desc->address_space.handler; | 234 | handler = handler_desc->address_space.handler; |
| 234 | 235 | address = (region_obj->region.address + region_offset); | |
| 235 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, | ||
| 236 | "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", | ||
| 237 | ®ion_obj->region.handler->address_space, handler, | ||
| 238 | ACPI_FORMAT_NATIVE_UINT(region_obj->region.address + | ||
| 239 | region_offset), | ||
| 240 | acpi_ut_get_region_name(region_obj->region. | ||
| 241 | space_id))); | ||
| 242 | 236 | ||
| 243 | /* | 237 | /* |
| 244 | * Special handling for generic_serial_bus and general_purpose_io: | 238 | * Special handling for generic_serial_bus and general_purpose_io: |
| 245 | * There are three extra parameters that must be passed to the | 239 | * There are three extra parameters that must be passed to the |
| 246 | * handler via the context: | 240 | * handler via the context: |
| 247 | * 1) Connection buffer, a resource template from Connection() op. | 241 | * 1) Connection buffer, a resource template from Connection() op |
| 248 | * 2) Length of the above buffer. | 242 | * 2) Length of the above buffer |
| 249 | * 3) Actual access length from the access_as() op. | 243 | * 3) Actual access length from the access_as() op |
| 244 | * | ||
| 245 | * In addition, for general_purpose_io, the Address and bit_width fields | ||
| 246 | * are defined as follows: | ||
| 247 | * 1) Address is the pin number index of the field (bit offset from | ||
| 248 | * the previous Connection) | ||
| 249 | * 2) bit_width is the actual bit length of the field (number of pins) | ||
| 250 | */ | 250 | */ |
| 251 | if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) || | 251 | if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && |
| 252 | (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) && | ||
| 253 | context && field_obj) { | 252 | context && field_obj) { |
| 254 | 253 | ||
| 255 | /* Get the Connection (resource_template) buffer */ | 254 | /* Get the Connection (resource_template) buffer */ |
| @@ -258,6 +257,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
| 258 | context->length = field_obj->field.resource_length; | 257 | context->length = field_obj->field.resource_length; |
| 259 | context->access_length = field_obj->field.access_length; | 258 | context->access_length = field_obj->field.access_length; |
| 260 | } | 259 | } |
| 260 | if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && | ||
| 261 | context && field_obj) { | ||
| 262 | |||
| 263 | /* Get the Connection (resource_template) buffer */ | ||
| 264 | |||
| 265 | context->connection = field_obj->field.resource_buffer; | ||
| 266 | context->length = field_obj->field.resource_length; | ||
| 267 | context->access_length = field_obj->field.access_length; | ||
| 268 | address = field_obj->field.pin_number_index; | ||
| 269 | bit_width = field_obj->field.bit_length; | ||
| 270 | } | ||
| 271 | |||
| 272 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, | ||
| 273 | "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", | ||
| 274 | ®ion_obj->region.handler->address_space, handler, | ||
| 275 | ACPI_FORMAT_NATIVE_UINT(address), | ||
| 276 | acpi_ut_get_region_name(region_obj->region. | ||
| 277 | space_id))); | ||
| 261 | 278 | ||
| 262 | if (!(handler_desc->address_space.handler_flags & | 279 | if (!(handler_desc->address_space.handler_flags & |
| 263 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { | 280 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { |
| @@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
| 271 | 288 | ||
| 272 | /* Call the handler */ | 289 | /* Call the handler */ |
| 273 | 290 | ||
| 274 | status = handler(function, | 291 | status = handler(function, address, bit_width, value, context, |
| 275 | (region_obj->region.address + region_offset), | ||
| 276 | bit_width, value, context, | ||
| 277 | region_obj2->extra.region_context); | 292 | region_obj2->extra.region_context); |
| 278 | 293 | ||
| 279 | if (ACPI_FAILURE(status)) { | 294 | if (ACPI_FAILURE(status)) { |
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 6907ce0c704c..b994845ed359 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c | |||
| @@ -253,6 +253,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, | |||
| 253 | buffer = &buffer_desc->integer.value; | 253 | buffer = &buffer_desc->integer.value; |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && | ||
| 257 | (obj_desc->field.region_obj->region.space_id == | ||
| 258 | ACPI_ADR_SPACE_GPIO)) { | ||
| 259 | /* | ||
| 260 | * For GPIO (general_purpose_io), the Address will be the bit offset | ||
| 261 | * from the previous Connection() operator, making it effectively a | ||
| 262 | * pin number index. The bit_length is the length of the field, which | ||
| 263 | * is thus the number of pins. | ||
| 264 | */ | ||
| 265 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | ||
| 266 | "GPIO FieldRead [FROM]: Pin %u Bits %u\n", | ||
| 267 | obj_desc->field.pin_number_index, | ||
| 268 | obj_desc->field.bit_length)); | ||
| 269 | |||
| 270 | /* Lock entire transaction if requested */ | ||
| 271 | |||
| 272 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); | ||
| 273 | |||
| 274 | /* Perform the write */ | ||
| 275 | |||
| 276 | status = acpi_ex_access_region(obj_desc, 0, | ||
| 277 | (u64 *)buffer, ACPI_READ); | ||
| 278 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); | ||
| 279 | if (ACPI_FAILURE(status)) { | ||
| 280 | acpi_ut_remove_reference(buffer_desc); | ||
| 281 | } else { | ||
| 282 | *ret_buffer_desc = buffer_desc; | ||
| 283 | } | ||
| 284 | return_ACPI_STATUS(status); | ||
| 285 | } | ||
| 286 | |||
| 256 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | 287 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
| 257 | "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", | 288 | "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", |
| 258 | obj_desc, obj_desc->common.type, buffer, | 289 | obj_desc, obj_desc->common.type, buffer, |
| @@ -413,6 +444,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
| 413 | 444 | ||
| 414 | *result_desc = buffer_desc; | 445 | *result_desc = buffer_desc; |
| 415 | return_ACPI_STATUS(status); | 446 | return_ACPI_STATUS(status); |
| 447 | } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && | ||
| 448 | (obj_desc->field.region_obj->region.space_id == | ||
| 449 | ACPI_ADR_SPACE_GPIO)) { | ||
| 450 | /* | ||
| 451 | * For GPIO (general_purpose_io), we will bypass the entire field | ||
| 452 | * mechanism and handoff the bit address and bit width directly to | ||
| 453 | * the handler. The Address will be the bit offset | ||
| 454 | * from the previous Connection() operator, making it effectively a | ||
| 455 | * pin number index. The bit_length is the length of the field, which | ||
| 456 | * is thus the number of pins. | ||
| 457 | */ | ||
| 458 | if (source_desc->common.type != ACPI_TYPE_INTEGER) { | ||
| 459 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
| 460 | } | ||
| 461 | |||
| 462 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | ||
| 463 | "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", | ||
| 464 | acpi_ut_get_type_name(source_desc->common. | ||
| 465 | type), | ||
| 466 | source_desc->common.type, | ||
| 467 | (u32)source_desc->integer.value, | ||
| 468 | obj_desc->field.pin_number_index, | ||
| 469 | obj_desc->field.bit_length)); | ||
| 470 | |||
| 471 | buffer = &source_desc->integer.value; | ||
| 472 | |||
| 473 | /* Lock entire transaction if requested */ | ||
| 474 | |||
| 475 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); | ||
| 476 | |||
| 477 | /* Perform the write */ | ||
| 478 | |||
| 479 | status = acpi_ex_access_region(obj_desc, 0, | ||
| 480 | (u64 *)buffer, ACPI_WRITE); | ||
| 481 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); | ||
| 482 | return_ACPI_STATUS(status); | ||
| 416 | } | 483 | } |
| 417 | 484 | ||
| 418 | /* Get a pointer to the data to be written */ | 485 | /* Get a pointer to the data to be written */ |
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index ee3f872870bc..118e942005e5 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c | |||
| @@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | |||
| 484 | obj_desc->field.resource_length = info->resource_length; | 484 | obj_desc->field.resource_length = info->resource_length; |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | obj_desc->field.pin_number_index = info->pin_number_index; | ||
| 488 | |||
| 487 | /* Allow full data read from EC address space */ | 489 | /* Allow full data read from EC address space */ |
| 488 | 490 | ||
| 489 | if ((obj_desc->field.region_obj->region.space_id == | 491 | if ((obj_desc->field.region_obj->region.space_id == |
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 76f7cff64594..c8ead9f97375 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
| @@ -99,6 +99,13 @@ static void container_device_detach(struct acpi_device *adev) | |||
| 99 | device_unregister(dev); | 99 | device_unregister(dev); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static void container_device_online(struct acpi_device *adev) | ||
| 103 | { | ||
| 104 | struct device *dev = acpi_driver_data(adev); | ||
| 105 | |||
| 106 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); | ||
| 107 | } | ||
| 108 | |||
| 102 | static struct acpi_scan_handler container_handler = { | 109 | static struct acpi_scan_handler container_handler = { |
| 103 | .ids = container_device_ids, | 110 | .ids = container_device_ids, |
| 104 | .attach = container_device_attach, | 111 | .attach = container_device_attach, |
| @@ -106,6 +113,7 @@ static struct acpi_scan_handler container_handler = { | |||
| 106 | .hotplug = { | 113 | .hotplug = { |
| 107 | .enabled = true, | 114 | .enabled = true, |
| 108 | .demand_offline = true, | 115 | .demand_offline = true, |
| 116 | .notify_online = container_device_online, | ||
| 109 | }, | 117 | }, |
| 110 | }; | 118 | }; |
| 111 | 119 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3bf7764659a4..ae44d8654c82 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -130,7 +130,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 130 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | 130 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { |
| 131 | count = snprintf(&modalias[len], size, "%s:", id->id); | 131 | count = snprintf(&modalias[len], size, "%s:", id->id); |
| 132 | if (count < 0) | 132 | if (count < 0) |
| 133 | return EINVAL; | 133 | return -EINVAL; |
| 134 | if (count >= size) | 134 | if (count >= size) |
| 135 | return -ENOMEM; | 135 | return -ENOMEM; |
| 136 | len += count; | 136 | len += count; |
| @@ -2189,6 +2189,9 @@ static void acpi_bus_attach(struct acpi_device *device) | |||
| 2189 | ok: | 2189 | ok: |
| 2190 | list_for_each_entry(child, &device->children, node) | 2190 | list_for_each_entry(child, &device->children, node) |
| 2191 | acpi_bus_attach(child); | 2191 | acpi_bus_attach(child); |
| 2192 | |||
| 2193 | if (device->handler && device->handler->hotplug.notify_online) | ||
| 2194 | device->handler->hotplug.notify_online(device); | ||
| 2192 | } | 2195 | } |
| 2193 | 2196 | ||
| 2194 | /** | 2197 | /** |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index fcbda105616e..8e7e18567ae6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -750,6 +750,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 750 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"), | 750 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"), |
| 751 | }, | 751 | }, |
| 752 | }, | 752 | }, |
| 753 | { | ||
| 754 | .callback = video_disable_native_backlight, | ||
| 755 | .ident = "ThinkPad X201s", | ||
| 756 | .matches = { | ||
| 757 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 758 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), | ||
| 759 | }, | ||
| 760 | }, | ||
| 753 | 761 | ||
| 754 | /* The native backlight controls do not work on some older machines */ | 762 | /* The native backlight controls do not work on some older machines */ |
| 755 | { | 763 | { |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d9fdeddcef96..6e93e7f98358 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -1289,6 +1289,8 @@ err_get_freq: | |||
| 1289 | per_cpu(cpufreq_cpu_data, j) = NULL; | 1289 | per_cpu(cpufreq_cpu_data, j) = NULL; |
| 1290 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1290 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 1291 | 1291 | ||
| 1292 | up_write(&policy->rwsem); | ||
| 1293 | |||
| 1292 | if (cpufreq_driver->exit) | 1294 | if (cpufreq_driver->exit) |
| 1293 | cpufreq_driver->exit(policy); | 1295 | cpufreq_driver->exit(policy); |
| 1294 | err_set_policy_cpu: | 1296 | err_set_policy_cpu: |
| @@ -1656,6 +1658,8 @@ void cpufreq_suspend(void) | |||
| 1656 | if (!cpufreq_driver) | 1658 | if (!cpufreq_driver) |
| 1657 | return; | 1659 | return; |
| 1658 | 1660 | ||
| 1661 | cpufreq_suspended = true; | ||
| 1662 | |||
| 1659 | if (!has_target()) | 1663 | if (!has_target()) |
| 1660 | return; | 1664 | return; |
| 1661 | 1665 | ||
| @@ -1670,8 +1674,6 @@ void cpufreq_suspend(void) | |||
| 1670 | pr_err("%s: Failed to suspend driver: %p\n", __func__, | 1674 | pr_err("%s: Failed to suspend driver: %p\n", __func__, |
| 1671 | policy); | 1675 | policy); |
| 1672 | } | 1676 | } |
| 1673 | |||
| 1674 | cpufreq_suspended = true; | ||
| 1675 | } | 1677 | } |
| 1676 | 1678 | ||
| 1677 | /** | 1679 | /** |
| @@ -1687,13 +1689,13 @@ void cpufreq_resume(void) | |||
| 1687 | if (!cpufreq_driver) | 1689 | if (!cpufreq_driver) |
| 1688 | return; | 1690 | return; |
| 1689 | 1691 | ||
| 1692 | cpufreq_suspended = false; | ||
| 1693 | |||
| 1690 | if (!has_target()) | 1694 | if (!has_target()) |
| 1691 | return; | 1695 | return; |
| 1692 | 1696 | ||
| 1693 | pr_debug("%s: Resuming Governors\n", __func__); | 1697 | pr_debug("%s: Resuming Governors\n", __func__); |
| 1694 | 1698 | ||
| 1695 | cpufreq_suspended = false; | ||
| 1696 | |||
| 1697 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { | 1699 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { |
| 1698 | if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) | 1700 | if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) |
| 1699 | pr_err("%s: Failed to resume driver: %p\n", __func__, | 1701 | pr_err("%s: Failed to resume driver: %p\n", __func__, |
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index d62eaaa75397..687476fb39e3 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
| @@ -377,8 +377,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, | |||
| 377 | struct gpio_chip *chip = achip->chip; | 377 | struct gpio_chip *chip = achip->chip; |
| 378 | struct acpi_resource_gpio *agpio; | 378 | struct acpi_resource_gpio *agpio; |
| 379 | struct acpi_resource *ares; | 379 | struct acpi_resource *ares; |
| 380 | int pin_index = (int)address; | ||
| 380 | acpi_status status; | 381 | acpi_status status; |
| 381 | bool pull_up; | 382 | bool pull_up; |
| 383 | int length; | ||
| 382 | int i; | 384 | int i; |
| 383 | 385 | ||
| 384 | status = acpi_buffer_to_resource(achip->conn_info.connection, | 386 | status = acpi_buffer_to_resource(achip->conn_info.connection, |
| @@ -400,7 +402,8 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, | |||
| 400 | return AE_BAD_PARAMETER; | 402 | return AE_BAD_PARAMETER; |
| 401 | } | 403 | } |
| 402 | 404 | ||
| 403 | for (i = 0; i < agpio->pin_table_length; i++) { | 405 | length = min(agpio->pin_table_length, (u16)(pin_index + bits)); |
| 406 | for (i = pin_index; i < length; ++i) { | ||
| 404 | unsigned pin = agpio->pin_table[i]; | 407 | unsigned pin = agpio->pin_table[i]; |
| 405 | struct acpi_gpio_connection *conn; | 408 | struct acpi_gpio_connection *conn; |
| 406 | struct gpio_desc *desc; | 409 | struct gpio_desc *desc; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index d91e59b79f0d..57ee0528aacb 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -118,6 +118,7 @@ struct acpi_device; | |||
| 118 | struct acpi_hotplug_profile { | 118 | struct acpi_hotplug_profile { |
| 119 | struct kobject kobj; | 119 | struct kobject kobj; |
| 120 | int (*scan_dependent)(struct acpi_device *adev); | 120 | int (*scan_dependent)(struct acpi_device *adev); |
| 121 | void (*notify_online)(struct acpi_device *adev); | ||
| 121 | bool enabled:1; | 122 | bool enabled:1; |
| 122 | bool demand_offline:1; | 123 | bool demand_offline:1; |
| 123 | }; | 124 | }; |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index c4b8093c80b3..f1604d8cf489 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
| @@ -725,14 +725,6 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
| 725 | clear_bit(bit, addr); | 725 | clear_bit(bit, addr); |
| 726 | } | 726 | } |
| 727 | 727 | ||
| 728 | static void memory_bm_clear_current(struct memory_bitmap *bm) | ||
| 729 | { | ||
| 730 | int bit; | ||
| 731 | |||
| 732 | bit = max(bm->cur.node_bit - 1, 0); | ||
| 733 | clear_bit(bit, bm->cur.node->data); | ||
| 734 | } | ||
| 735 | |||
| 736 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | 728 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) |
| 737 | { | 729 | { |
| 738 | void *addr; | 730 | void *addr; |
| @@ -1341,35 +1333,23 @@ static struct memory_bitmap copy_bm; | |||
| 1341 | 1333 | ||
| 1342 | void swsusp_free(void) | 1334 | void swsusp_free(void) |
| 1343 | { | 1335 | { |
| 1344 | unsigned long fb_pfn, fr_pfn; | 1336 | struct zone *zone; |
| 1345 | 1337 | unsigned long pfn, max_zone_pfn; | |
| 1346 | memory_bm_position_reset(forbidden_pages_map); | ||
| 1347 | memory_bm_position_reset(free_pages_map); | ||
| 1348 | |||
| 1349 | loop: | ||
| 1350 | fr_pfn = memory_bm_next_pfn(free_pages_map); | ||
| 1351 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); | ||
| 1352 | |||
| 1353 | /* | ||
| 1354 | * Find the next bit set in both bitmaps. This is guaranteed to | ||
| 1355 | * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP. | ||
| 1356 | */ | ||
| 1357 | do { | ||
| 1358 | if (fb_pfn < fr_pfn) | ||
| 1359 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); | ||
| 1360 | if (fr_pfn < fb_pfn) | ||
| 1361 | fr_pfn = memory_bm_next_pfn(free_pages_map); | ||
| 1362 | } while (fb_pfn != fr_pfn); | ||
| 1363 | |||
| 1364 | if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) { | ||
| 1365 | struct page *page = pfn_to_page(fr_pfn); | ||
| 1366 | 1338 | ||
| 1367 | memory_bm_clear_current(forbidden_pages_map); | 1339 | for_each_populated_zone(zone) { |
| 1368 | memory_bm_clear_current(free_pages_map); | 1340 | max_zone_pfn = zone_end_pfn(zone); |
| 1369 | __free_page(page); | 1341 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) |
| 1370 | goto loop; | 1342 | if (pfn_valid(pfn)) { |
| 1343 | struct page *page = pfn_to_page(pfn); | ||
| 1344 | |||
| 1345 | if (swsusp_page_is_forbidden(page) && | ||
| 1346 | swsusp_page_is_free(page)) { | ||
| 1347 | swsusp_unset_page_forbidden(page); | ||
| 1348 | swsusp_unset_page_free(page); | ||
| 1349 | __free_page(page); | ||
| 1350 | } | ||
| 1351 | } | ||
| 1371 | } | 1352 | } |
| 1372 | |||
| 1373 | nr_copy_pages = 0; | 1353 | nr_copy_pages = 0; |
| 1374 | nr_meta_pages = 0; | 1354 | nr_meta_pages = 0; |
| 1375 | restore_pblist = NULL; | 1355 | restore_pblist = NULL; |
