diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:32:11 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:32:11 -0400 |
| commit | c11f6c82581e8be4e1829c677db54e7f55cebece (patch) | |
| tree | 1a116241b0831ded998aabe800bdc24104cbd826 /drivers | |
| parent | 40aba218969914d1b225e742617adb921cf94eae (diff) | |
| parent | 193a6dec1c0246a80b6d0101e4f351ccf877bcac (diff) | |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (119 commits)
ACPI: don't pass handle for fixed hardware notifications
ACPI: remove null pointer checks in deferred execution path
ACPI: simplify deferred execution path
acerhdf: additional BIOS versions
acerhdf: convert to dev_pm_ops
acerhdf: fix fan control for AOA150 model
thermal: add missing Kconfig dependency
acpi: switch /proc/acpi/{debug_layer,debug_level} to seq_file
hp-wmi: fix rfkill memory leak on unload
ACPI: remove unnecessary #ifdef CONFIG_DMI
ACPI: linux/acpi.h should not include linux/dmi.h
hwmon driver for ACPI 4.0 power meters
topstar-laptop: add new driver for hotkeys support on Topstar N01
thinkpad_acpi: fix rfkill memory leak on unload
thinkpad-acpi: report brightness events when required
thinkpad-acpi: don't poll by default any of the reserved hotkeys
thinkpad-acpi: Fix procfs hotkey reset command
thinkpad-acpi: deprecate hotkey_bios_mask
thinkpad-acpi: hotkey poll fixes
thinkpad-acpi: be more strict when detecting a ThinkPad
...
Diffstat (limited to 'drivers')
108 files changed, 5496 insertions, 2258 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7ec7d88c5999..dd8729d674e5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -60,7 +60,11 @@ config ACPI_PROCFS | |||
| 60 | /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) | 60 | /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) |
| 61 | /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) | 61 | /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) |
| 62 | /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) | 62 | /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) |
| 63 | 63 | /proc/acpi/processor/*/power (/sys/devices/system/cpu/*/cpuidle/*) | |
| 64 | /proc/acpi/processor/*/performance (/sys/devices/system/cpu/*/ | ||
| 65 | cpufreq/*) | ||
| 66 | /proc/acpi/processor/*/throttling (/sys/class/thermal/ | ||
| 67 | cooling_device*/*) | ||
| 64 | This option has no effect on /proc/acpi/ files | 68 | This option has no effect on /proc/acpi/ files |
| 65 | and functions which do not yet exist in /sys. | 69 | and functions which do not yet exist in /sys. |
| 66 | 70 | ||
| @@ -82,6 +86,17 @@ config ACPI_PROCFS_POWER | |||
| 82 | 86 | ||
| 83 | Say N to delete power /proc/acpi/ directories that have moved to /sys/ | 87 | Say N to delete power /proc/acpi/ directories that have moved to /sys/ |
| 84 | 88 | ||
| 89 | config ACPI_POWER_METER | ||
| 90 | tristate "ACPI 4.0 power meter" | ||
| 91 | depends on HWMON | ||
| 92 | help | ||
| 93 | This driver exposes ACPI 4.0 power meters as hardware monitoring | ||
| 94 | devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware | ||
| 95 | and a power meter. | ||
| 96 | |||
| 97 | To compile this driver as a module, choose M here: | ||
| 98 | the module will be called power-meter. | ||
| 99 | |||
| 85 | config ACPI_SYSFS_POWER | 100 | config ACPI_SYSFS_POWER |
| 86 | bool "Future power /sys interface" | 101 | bool "Future power /sys interface" |
| 87 | select POWER_SUPPLY | 102 | select POWER_SUPPLY |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 03a985be3fe3..82cd49dc603b 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
| @@ -56,6 +56,7 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o | |||
| 56 | obj-$(CONFIG_ACPI_BATTERY) += battery.o | 56 | obj-$(CONFIG_ACPI_BATTERY) += battery.o |
| 57 | obj-$(CONFIG_ACPI_SBS) += sbshc.o | 57 | obj-$(CONFIG_ACPI_SBS) += sbshc.o |
| 58 | obj-$(CONFIG_ACPI_SBS) += sbs.o | 58 | obj-$(CONFIG_ACPI_SBS) += sbs.o |
| 59 | obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o | ||
| 59 | 60 | ||
| 60 | # processor has its own "processor." module_param namespace | 61 | # processor has its own "processor." module_param namespace |
| 61 | processor-y := processor_core.o processor_throttling.o | 62 | processor-y := processor_core.o processor_throttling.o |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 0df8fcb687d6..98b9690b0159 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
| @@ -37,6 +37,8 @@ | |||
| 37 | #include <acpi/acpi_bus.h> | 37 | #include <acpi/acpi_bus.h> |
| 38 | #include <acpi/acpi_drivers.h> | 38 | #include <acpi/acpi_drivers.h> |
| 39 | 39 | ||
| 40 | #define PREFIX "ACPI: " | ||
| 41 | |||
| 40 | #define ACPI_AC_CLASS "ac_adapter" | 42 | #define ACPI_AC_CLASS "ac_adapter" |
| 41 | #define ACPI_AC_DEVICE_NAME "AC Adapter" | 43 | #define ACPI_AC_DEVICE_NAME "AC Adapter" |
| 42 | #define ACPI_AC_FILE_STATE "state" | 44 | #define ACPI_AC_FILE_STATE "state" |
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 9a62224cc278..28ccdbc05ac8 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
| @@ -53,7 +53,6 @@ MODULE_LICENSE("GPL"); | |||
| 53 | 53 | ||
| 54 | static int acpi_memory_device_add(struct acpi_device *device); | 54 | static int acpi_memory_device_add(struct acpi_device *device); |
| 55 | static int acpi_memory_device_remove(struct acpi_device *device, int type); | 55 | static int acpi_memory_device_remove(struct acpi_device *device, int type); |
| 56 | static int acpi_memory_device_start(struct acpi_device *device); | ||
| 57 | 56 | ||
| 58 | static const struct acpi_device_id memory_device_ids[] = { | 57 | static const struct acpi_device_id memory_device_ids[] = { |
| 59 | {ACPI_MEMORY_DEVICE_HID, 0}, | 58 | {ACPI_MEMORY_DEVICE_HID, 0}, |
| @@ -68,7 +67,6 @@ static struct acpi_driver acpi_memory_device_driver = { | |||
| 68 | .ops = { | 67 | .ops = { |
| 69 | .add = acpi_memory_device_add, | 68 | .add = acpi_memory_device_add, |
| 70 | .remove = acpi_memory_device_remove, | 69 | .remove = acpi_memory_device_remove, |
| 71 | .start = acpi_memory_device_start, | ||
| 72 | }, | 70 | }, |
| 73 | }; | 71 | }; |
| 74 | 72 | ||
| @@ -431,28 +429,6 @@ static int acpi_memory_device_add(struct acpi_device *device) | |||
| 431 | 429 | ||
| 432 | printk(KERN_DEBUG "%s \n", acpi_device_name(device)); | 430 | printk(KERN_DEBUG "%s \n", acpi_device_name(device)); |
| 433 | 431 | ||
| 434 | return result; | ||
| 435 | } | ||
| 436 | |||
| 437 | static int acpi_memory_device_remove(struct acpi_device *device, int type) | ||
| 438 | { | ||
| 439 | struct acpi_memory_device *mem_device = NULL; | ||
| 440 | |||
| 441 | |||
| 442 | if (!device || !acpi_driver_data(device)) | ||
| 443 | return -EINVAL; | ||
| 444 | |||
| 445 | mem_device = acpi_driver_data(device); | ||
| 446 | kfree(mem_device); | ||
| 447 | |||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | static int acpi_memory_device_start (struct acpi_device *device) | ||
| 452 | { | ||
| 453 | struct acpi_memory_device *mem_device; | ||
| 454 | int result = 0; | ||
| 455 | |||
| 456 | /* | 432 | /* |
| 457 | * Early boot code has recognized memory area by EFI/E820. | 433 | * Early boot code has recognized memory area by EFI/E820. |
| 458 | * If DSDT shows these memory devices on boot, hotplug is not necessary | 434 | * If DSDT shows these memory devices on boot, hotplug is not necessary |
| @@ -462,8 +438,6 @@ static int acpi_memory_device_start (struct acpi_device *device) | |||
| 462 | if (!acpi_hotmem_initialized) | 438 | if (!acpi_hotmem_initialized) |
| 463 | return 0; | 439 | return 0; |
| 464 | 440 | ||
| 465 | mem_device = acpi_driver_data(device); | ||
| 466 | |||
| 467 | if (!acpi_memory_check_device(mem_device)) { | 441 | if (!acpi_memory_check_device(mem_device)) { |
| 468 | /* call add_memory func */ | 442 | /* call add_memory func */ |
| 469 | result = acpi_memory_enable_device(mem_device); | 443 | result = acpi_memory_enable_device(mem_device); |
| @@ -474,6 +448,20 @@ static int acpi_memory_device_start (struct acpi_device *device) | |||
| 474 | return result; | 448 | return result; |
| 475 | } | 449 | } |
| 476 | 450 | ||
| 451 | static int acpi_memory_device_remove(struct acpi_device *device, int type) | ||
| 452 | { | ||
| 453 | struct acpi_memory_device *mem_device = NULL; | ||
| 454 | |||
| 455 | |||
| 456 | if (!device || !acpi_driver_data(device)) | ||
| 457 | return -EINVAL; | ||
| 458 | |||
| 459 | mem_device = acpi_driver_data(device); | ||
| 460 | kfree(mem_device); | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 477 | /* | 465 | /* |
| 478 | * Helper function to check for memory device | 466 | * Helper function to check for memory device |
| 479 | */ | 467 | */ |
| @@ -481,26 +469,23 @@ static acpi_status is_memory_device(acpi_handle handle) | |||
| 481 | { | 469 | { |
| 482 | char *hardware_id; | 470 | char *hardware_id; |
| 483 | acpi_status status; | 471 | acpi_status status; |
| 484 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 485 | struct acpi_device_info *info; | 472 | struct acpi_device_info *info; |
| 486 | 473 | ||
| 487 | 474 | status = acpi_get_object_info(handle, &info); | |
| 488 | status = acpi_get_object_info(handle, &buffer); | ||
| 489 | if (ACPI_FAILURE(status)) | 475 | if (ACPI_FAILURE(status)) |
| 490 | return status; | 476 | return status; |
| 491 | 477 | ||
| 492 | info = buffer.pointer; | ||
| 493 | if (!(info->valid & ACPI_VALID_HID)) { | 478 | if (!(info->valid & ACPI_VALID_HID)) { |
| 494 | kfree(buffer.pointer); | 479 | kfree(info); |
| 495 | return AE_ERROR; | 480 | return AE_ERROR; |
| 496 | } | 481 | } |
| 497 | 482 | ||
| 498 | hardware_id = info->hardware_id.value; | 483 | hardware_id = info->hardware_id.string; |
| 499 | if ((hardware_id == NULL) || | 484 | if ((hardware_id == NULL) || |
| 500 | (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID))) | 485 | (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID))) |
| 501 | status = AE_ERROR; | 486 | status = AE_ERROR; |
| 502 | 487 | ||
| 503 | kfree(buffer.pointer); | 488 | kfree(info); |
| 504 | return status; | 489 | return status; |
| 505 | } | 490 | } |
| 506 | 491 | ||
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 72ac28da14e3..e7973bc16846 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile | |||
| @@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o | |||
| 28 | acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \ | 28 | acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \ |
| 29 | nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ | 29 | nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ |
| 30 | nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ | 30 | nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ |
| 31 | nsparse.o nspredef.o | 31 | nsparse.o nspredef.o nsrepair.o |
| 32 | 32 | ||
| 33 | acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o | 33 | acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o |
| 34 | 34 | ||
| @@ -44,4 +44,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o | |||
| 44 | 44 | ||
| 45 | acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ | 45 | acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ |
| 46 | utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ | 46 | utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ |
| 47 | utstate.o utmutex.o utobject.o utresrc.o utlock.o | 47 | utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o |
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h index e6777fb883d2..8e679ef5b231 100644 --- a/drivers/acpi/acpica/acconfig.h +++ b/drivers/acpi/acpica/acconfig.h | |||
| @@ -183,7 +183,7 @@ | |||
| 183 | 183 | ||
| 184 | /* Operation regions */ | 184 | /* Operation regions */ |
| 185 | 185 | ||
| 186 | #define ACPI_NUM_PREDEFINED_REGIONS 8 | 186 | #define ACPI_NUM_PREDEFINED_REGIONS 9 |
| 187 | #define ACPI_USER_REGION_BEGIN 0x80 | 187 | #define ACPI_USER_REGION_BEGIN 0x80 |
| 188 | 188 | ||
| 189 | /* Maximum space_ids for Operation Regions */ | 189 | /* Maximum space_ids for Operation Regions */ |
| @@ -199,9 +199,15 @@ | |||
| 199 | #define ACPI_RSDP_CHECKSUM_LENGTH 20 | 199 | #define ACPI_RSDP_CHECKSUM_LENGTH 20 |
| 200 | #define ACPI_RSDP_XCHECKSUM_LENGTH 36 | 200 | #define ACPI_RSDP_XCHECKSUM_LENGTH 36 |
| 201 | 201 | ||
| 202 | /* SMBus bidirectional buffer size */ | 202 | /* SMBus and IPMI bidirectional buffer size */ |
| 203 | 203 | ||
| 204 | #define ACPI_SMBUS_BUFFER_SIZE 34 | 204 | #define ACPI_SMBUS_BUFFER_SIZE 34 |
| 205 | #define ACPI_IPMI_BUFFER_SIZE 66 | ||
| 206 | |||
| 207 | /* _sx_d and _sx_w control methods */ | ||
| 208 | |||
| 209 | #define ACPI_NUM_sx_d_METHODS 4 | ||
| 210 | #define ACPI_NUM_sx_w_METHODS 5 | ||
| 205 | 211 | ||
| 206 | /****************************************************************************** | 212 | /****************************************************************************** |
| 207 | * | 213 | * |
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 62c59df3b86c..a4fb001d96f1 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h | |||
| @@ -154,10 +154,6 @@ void | |||
| 154 | acpi_db_display_argument_object(union acpi_operand_object *obj_desc, | 154 | acpi_db_display_argument_object(union acpi_operand_object *obj_desc, |
| 155 | struct acpi_walk_state *walk_state); | 155 | struct acpi_walk_state *walk_state); |
| 156 | 156 | ||
| 157 | void acpi_db_check_predefined_names(void); | ||
| 158 | |||
| 159 | void acpi_db_batch_execute(void); | ||
| 160 | |||
| 161 | /* | 157 | /* |
| 162 | * dbexec - debugger control method execution | 158 | * dbexec - debugger control method execution |
| 163 | */ | 159 | */ |
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 3d87362d17ed..29ba66d5a790 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
| @@ -58,6 +58,10 @@ | |||
| 58 | #define ACPI_INIT_GLOBAL(a,b) a | 58 | #define ACPI_INIT_GLOBAL(a,b) a |
| 59 | #endif | 59 | #endif |
| 60 | 60 | ||
| 61 | #ifdef DEFINE_ACPI_GLOBALS | ||
| 62 | |||
| 63 | /* Public globals, available from outside ACPICA subsystem */ | ||
| 64 | |||
| 61 | /***************************************************************************** | 65 | /***************************************************************************** |
| 62 | * | 66 | * |
| 63 | * Runtime configuration (static defaults that can be overriden at runtime) | 67 | * Runtime configuration (static defaults that can be overriden at runtime) |
| @@ -78,7 +82,7 @@ | |||
| 78 | * 5) Allow unresolved references (invalid target name) in package objects | 82 | * 5) Allow unresolved references (invalid target name) in package objects |
| 79 | * 6) Enable warning messages for behavior that is not ACPI spec compliant | 83 | * 6) Enable warning messages for behavior that is not ACPI spec compliant |
| 80 | */ | 84 | */ |
| 81 | ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); | 85 | u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); |
| 82 | 86 | ||
| 83 | /* | 87 | /* |
| 84 | * Automatically serialize ALL control methods? Default is FALSE, meaning | 88 | * Automatically serialize ALL control methods? Default is FALSE, meaning |
| @@ -86,27 +90,36 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); | |||
| 86 | * Only change this if the ASL code is poorly written and cannot handle | 90 | * Only change this if the ASL code is poorly written and cannot handle |
| 87 | * reentrancy even though methods are marked "NotSerialized". | 91 | * reentrancy even though methods are marked "NotSerialized". |
| 88 | */ | 92 | */ |
| 89 | ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); | 93 | u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); |
| 90 | 94 | ||
| 91 | /* | 95 | /* |
| 92 | * Create the predefined _OSI method in the namespace? Default is TRUE | 96 | * Create the predefined _OSI method in the namespace? Default is TRUE |
| 93 | * because ACPI CA is fully compatible with other ACPI implementations. | 97 | * because ACPI CA is fully compatible with other ACPI implementations. |
| 94 | * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. | 98 | * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. |
| 95 | */ | 99 | */ |
| 96 | ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); | 100 | u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); |
| 97 | 101 | ||
| 98 | /* | 102 | /* |
| 99 | * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and | 103 | * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and |
| 100 | * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only | 104 | * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only |
| 101 | * be enabled just before going to sleep. | 105 | * be enabled just before going to sleep. |
| 102 | */ | 106 | */ |
| 103 | ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); | 107 | u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); |
| 104 | 108 | ||
| 105 | /* | 109 | /* |
| 106 | * Optionally use default values for the ACPI register widths. Set this to | 110 | * Optionally use default values for the ACPI register widths. Set this to |
| 107 | * TRUE to use the defaults, if an FADT contains incorrect widths/lengths. | 111 | * TRUE to use the defaults, if an FADT contains incorrect widths/lengths. |
| 108 | */ | 112 | */ |
| 109 | ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); | 113 | u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); |
| 114 | |||
| 115 | /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ | ||
| 116 | |||
| 117 | struct acpi_table_fadt acpi_gbl_FADT; | ||
| 118 | u32 acpi_current_gpe_count; | ||
| 119 | u32 acpi_gbl_trace_flags; | ||
| 120 | acpi_name acpi_gbl_trace_method_name; | ||
| 121 | |||
| 122 | #endif | ||
| 110 | 123 | ||
| 111 | /***************************************************************************** | 124 | /***************************************************************************** |
| 112 | * | 125 | * |
| @@ -114,11 +127,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); | |||
| 114 | * | 127 | * |
| 115 | ****************************************************************************/ | 128 | ****************************************************************************/ |
| 116 | 129 | ||
| 117 | /* Runtime configuration of debug print levels */ | ||
| 118 | |||
| 119 | extern u32 acpi_dbg_level; | ||
| 120 | extern u32 acpi_dbg_layer; | ||
| 121 | |||
| 122 | /* Procedure nesting level for debug output */ | 130 | /* Procedure nesting level for debug output */ |
| 123 | 131 | ||
| 124 | extern u32 acpi_gbl_nesting_level; | 132 | extern u32 acpi_gbl_nesting_level; |
| @@ -127,10 +135,8 @@ extern u32 acpi_gbl_nesting_level; | |||
| 127 | 135 | ||
| 128 | ACPI_EXTERN u32 acpi_gbl_original_dbg_level; | 136 | ACPI_EXTERN u32 acpi_gbl_original_dbg_level; |
| 129 | ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; | 137 | ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; |
| 130 | ACPI_EXTERN acpi_name acpi_gbl_trace_method_name; | ||
| 131 | ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; | 138 | ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; |
| 132 | ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; | 139 | ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; |
| 133 | ACPI_EXTERN u32 acpi_gbl_trace_flags; | ||
| 134 | 140 | ||
| 135 | /***************************************************************************** | 141 | /***************************************************************************** |
| 136 | * | 142 | * |
| @@ -142,10 +148,8 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags; | |||
| 142 | * acpi_gbl_root_table_list is the master list of ACPI tables found in the | 148 | * acpi_gbl_root_table_list is the master list of ACPI tables found in the |
| 143 | * RSDT/XSDT. | 149 | * RSDT/XSDT. |
| 144 | * | 150 | * |
| 145 | * acpi_gbl_FADT is a local copy of the FADT, converted to a common format. | ||
| 146 | */ | 151 | */ |
| 147 | ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; | 152 | ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; |
| 148 | ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT; | ||
| 149 | ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; | 153 | ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; |
| 150 | 154 | ||
| 151 | /* These addresses are calculated from the FADT Event Block addresses */ | 155 | /* These addresses are calculated from the FADT Event Block addresses */ |
| @@ -261,7 +265,8 @@ ACPI_EXTERN u8 acpi_gbl_osi_data; | |||
| 261 | extern u8 acpi_gbl_shutdown; | 265 | extern u8 acpi_gbl_shutdown; |
| 262 | extern u32 acpi_gbl_startup_flags; | 266 | extern u32 acpi_gbl_startup_flags; |
| 263 | extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; | 267 | extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; |
| 264 | extern const char *acpi_gbl_highest_dstate_names[4]; | 268 | extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS]; |
| 269 | extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS]; | ||
| 265 | extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; | 270 | extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; |
| 266 | extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; | 271 | extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; |
| 267 | 272 | ||
| @@ -290,6 +295,7 @@ extern char const *acpi_gbl_exception_names_ctrl[]; | |||
| 290 | ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; | 295 | ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; |
| 291 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; | 296 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; |
| 292 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; | 297 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; |
| 298 | ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list; | ||
| 293 | 299 | ||
| 294 | extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; | 300 | extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; |
| 295 | extern const struct acpi_predefined_names | 301 | extern const struct acpi_predefined_names |
| @@ -340,7 +346,6 @@ ACPI_EXTERN struct acpi_fixed_event_handler | |||
| 340 | ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; | 346 | ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; |
| 341 | ACPI_EXTERN struct acpi_gpe_block_info | 347 | ACPI_EXTERN struct acpi_gpe_block_info |
| 342 | *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; | 348 | *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; |
| 343 | ACPI_EXTERN u32 acpi_current_gpe_count; | ||
| 344 | 349 | ||
| 345 | /***************************************************************************** | 350 | /***************************************************************************** |
| 346 | * | 351 | * |
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 4afa3d8e0efb..36192f142fbb 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h | |||
| @@ -62,6 +62,14 @@ u32 acpi_hw_get_mode(void); | |||
| 62 | /* | 62 | /* |
| 63 | * hwregs - ACPI Register I/O | 63 | * hwregs - ACPI Register I/O |
| 64 | */ | 64 | */ |
| 65 | acpi_status | ||
| 66 | acpi_hw_validate_register(struct acpi_generic_address *reg, | ||
| 67 | u8 max_bit_width, u64 *address); | ||
| 68 | |||
| 69 | acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg); | ||
| 70 | |||
| 71 | acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg); | ||
| 72 | |||
| 65 | struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); | 73 | struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); |
| 66 | 74 | ||
| 67 | acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); | 75 | acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); |
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index e8db7a3143a5..5db9f2916f7c 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h | |||
| @@ -461,9 +461,9 @@ void acpi_ex_acquire_global_lock(u32 rule); | |||
| 461 | 461 | ||
| 462 | void acpi_ex_release_global_lock(u32 rule); | 462 | void acpi_ex_release_global_lock(u32 rule); |
| 463 | 463 | ||
| 464 | void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); | 464 | void acpi_ex_eisa_id_to_string(char *dest, acpi_integer compressed_id); |
| 465 | 465 | ||
| 466 | void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string); | 466 | void acpi_ex_integer_to_string(char *dest, acpi_integer value); |
| 467 | 467 | ||
| 468 | /* | 468 | /* |
| 469 | * exregion - default op_region handlers | 469 | * exregion - default op_region handlers |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index ee986edfa0da..81e64f478679 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
| @@ -369,6 +369,19 @@ union acpi_predefined_info { | |||
| 369 | struct acpi_package_info3 ret_info3; | 369 | struct acpi_package_info3 ret_info3; |
| 370 | }; | 370 | }; |
| 371 | 371 | ||
| 372 | /* Data block used during object validation */ | ||
| 373 | |||
| 374 | struct acpi_predefined_data { | ||
| 375 | char *pathname; | ||
| 376 | const union acpi_predefined_info *predefined; | ||
| 377 | u32 flags; | ||
| 378 | u8 node_flags; | ||
| 379 | }; | ||
| 380 | |||
| 381 | /* Defines for Flags field above */ | ||
| 382 | |||
| 383 | #define ACPI_OBJECT_REPAIRED 1 | ||
| 384 | |||
| 372 | /* | 385 | /* |
| 373 | * Bitmapped return value types | 386 | * Bitmapped return value types |
| 374 | * Note: the actual data types must be contiguous, a loop in nspredef.c | 387 | * Note: the actual data types must be contiguous, a loop in nspredef.c |
| @@ -885,6 +898,9 @@ struct acpi_bit_register_info { | |||
| 885 | #define ACPI_OSI_WIN_XP_SP2 0x05 | 898 | #define ACPI_OSI_WIN_XP_SP2 0x05 |
| 886 | #define ACPI_OSI_WINSRV_2003_SP1 0x06 | 899 | #define ACPI_OSI_WINSRV_2003_SP1 0x06 |
| 887 | #define ACPI_OSI_WIN_VISTA 0x07 | 900 | #define ACPI_OSI_WIN_VISTA 0x07 |
| 901 | #define ACPI_OSI_WINSRV_2008 0x08 | ||
| 902 | #define ACPI_OSI_WIN_VISTA_SP1 0x09 | ||
| 903 | #define ACPI_OSI_WIN_7 0x0A | ||
| 888 | 904 | ||
| 889 | #define ACPI_ALWAYS_ILLEGAL 0x00 | 905 | #define ACPI_ALWAYS_ILLEGAL 0x00 |
| 890 | 906 | ||
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 91ac7d7b4402..3acd9c6760ea 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h | |||
| @@ -340,6 +340,7 @@ | |||
| 340 | */ | 340 | */ |
| 341 | #define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e); | 341 | #define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e); |
| 342 | #define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e); | 342 | #define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e); |
| 343 | #define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist | ||
| 343 | 344 | ||
| 344 | #else | 345 | #else |
| 345 | 346 | ||
| @@ -347,6 +348,7 @@ | |||
| 347 | 348 | ||
| 348 | #define ACPI_ERROR_NAMESPACE(s, e) | 349 | #define ACPI_ERROR_NAMESPACE(s, e) |
| 349 | #define ACPI_ERROR_METHOD(s, n, p, e) | 350 | #define ACPI_ERROR_METHOD(s, n, p, e) |
| 351 | #define ACPI_WARN_PREDEFINED(plist) | ||
| 350 | #endif /* ACPI_NO_ERROR_MESSAGES */ | 352 | #endif /* ACPI_NO_ERROR_MESSAGES */ |
| 351 | 353 | ||
| 352 | /* | 354 | /* |
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 94cdc2b8cb93..09a2764c734b 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
| @@ -73,6 +73,14 @@ | |||
| 73 | #define ACPI_NS_WALK_UNLOCK 0x01 | 73 | #define ACPI_NS_WALK_UNLOCK 0x01 |
| 74 | #define ACPI_NS_WALK_TEMP_NODES 0x02 | 74 | #define ACPI_NS_WALK_TEMP_NODES 0x02 |
| 75 | 75 | ||
| 76 | /* Object is not a package element */ | ||
| 77 | |||
| 78 | #define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX | ||
| 79 | |||
| 80 | /* Always emit warning message, not dependent on node flags */ | ||
| 81 | |||
| 82 | #define ACPI_WARN_ALWAYS 0 | ||
| 83 | |||
| 76 | /* | 84 | /* |
| 77 | * nsinit - Namespace initialization | 85 | * nsinit - Namespace initialization |
| 78 | */ | 86 | */ |
| @@ -144,6 +152,8 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name); | |||
| 144 | 152 | ||
| 145 | void acpi_ns_delete_node(struct acpi_namespace_node *node); | 153 | void acpi_ns_delete_node(struct acpi_namespace_node *node); |
| 146 | 154 | ||
| 155 | void acpi_ns_remove_node(struct acpi_namespace_node *node); | ||
| 156 | |||
| 147 | void | 157 | void |
| 148 | acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle); | 158 | acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle); |
| 149 | 159 | ||
| @@ -186,6 +196,8 @@ acpi_ns_dump_objects(acpi_object_type type, | |||
| 186 | */ | 196 | */ |
| 187 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); | 197 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); |
| 188 | 198 | ||
| 199 | void acpi_ns_exec_module_code_list(void); | ||
| 200 | |||
| 189 | /* | 201 | /* |
| 190 | * nspredef - Support for predefined/reserved names | 202 | * nspredef - Support for predefined/reserved names |
| 191 | */ | 203 | */ |
| @@ -260,6 +272,19 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node, | |||
| 260 | acpi_object_handler handler, void **data); | 272 | acpi_object_handler handler, void **data); |
| 261 | 273 | ||
| 262 | /* | 274 | /* |
| 275 | * nsrepair - return object repair for predefined methods/objects | ||
| 276 | */ | ||
| 277 | acpi_status | ||
| 278 | acpi_ns_repair_object(struct acpi_predefined_data *data, | ||
| 279 | u32 expected_btypes, | ||
| 280 | u32 package_index, | ||
| 281 | union acpi_operand_object **return_object_ptr); | ||
| 282 | |||
| 283 | acpi_status | ||
| 284 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, | ||
| 285 | union acpi_operand_object **obj_desc_ptr); | ||
| 286 | |||
| 287 | /* | ||
| 263 | * nssearch - Namespace searching and entry | 288 | * nssearch - Namespace searching and entry |
| 264 | */ | 289 | */ |
| 265 | acpi_status | 290 | acpi_status |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index eb6f038b03d9..b39d682a2140 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | #define AOPOBJ_SETUP_COMPLETE 0x10 | 98 | #define AOPOBJ_SETUP_COMPLETE 0x10 |
| 99 | #define AOPOBJ_SINGLE_DATUM 0x20 | 99 | #define AOPOBJ_SINGLE_DATUM 0x20 |
| 100 | #define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ | 100 | #define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ |
| 101 | #define AOPOBJ_MODULE_LEVEL 0x80 | ||
| 101 | 102 | ||
| 102 | /****************************************************************************** | 103 | /****************************************************************************** |
| 103 | * | 104 | * |
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index 23ee0fbf5619..22881e8ce229 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h | |||
| @@ -62,6 +62,8 @@ | |||
| 62 | #define ACPI_PARSE_DEFERRED_OP 0x0100 | 62 | #define ACPI_PARSE_DEFERRED_OP 0x0100 |
| 63 | #define ACPI_PARSE_DISASSEMBLE 0x0200 | 63 | #define ACPI_PARSE_DISASSEMBLE 0x0200 |
| 64 | 64 | ||
| 65 | #define ACPI_PARSE_MODULE_LEVEL 0x0400 | ||
| 66 | |||
| 65 | /****************************************************************************** | 67 | /****************************************************************************** |
| 66 | * | 68 | * |
| 67 | * Parser interfaces | 69 | * Parser interfaces |
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 63f656ae3604..cd80d1dd1950 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h | |||
| @@ -64,8 +64,8 @@ | |||
| 64 | * (Used for _PRW) | 64 | * (Used for _PRW) |
| 65 | * | 65 | * |
| 66 | * | 66 | * |
| 67 | * 2) PTYPE2 packages contain a variable number of sub-packages. Each of the | 67 | * 2) PTYPE2 packages contain a Variable-length number of sub-packages. Each |
| 68 | * different types describe the contents of each of the sub-packages. | 68 | * of the different types describe the contents of each of the sub-packages. |
| 69 | * | 69 | * |
| 70 | * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: | 70 | * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: |
| 71 | * object type | 71 | * object type |
| @@ -91,6 +91,9 @@ | |||
| 91 | * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length | 91 | * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length |
| 92 | * (Used for _HPX) | 92 | * (Used for _HPX) |
| 93 | * | 93 | * |
| 94 | * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length | ||
| 95 | * (Used for _ART, _FPS) | ||
| 96 | * | ||
| 94 | *****************************************************************************/ | 97 | *****************************************************************************/ |
| 95 | 98 | ||
| 96 | enum acpi_return_package_types { | 99 | enum acpi_return_package_types { |
| @@ -101,9 +104,11 @@ enum acpi_return_package_types { | |||
| 101 | ACPI_PTYPE2_COUNT = 5, | 104 | ACPI_PTYPE2_COUNT = 5, |
| 102 | ACPI_PTYPE2_PKG_COUNT = 6, | 105 | ACPI_PTYPE2_PKG_COUNT = 6, |
| 103 | ACPI_PTYPE2_FIXED = 7, | 106 | ACPI_PTYPE2_FIXED = 7, |
| 104 | ACPI_PTYPE2_MIN = 8 | 107 | ACPI_PTYPE2_MIN = 8, |
| 108 | ACPI_PTYPE2_REV_FIXED = 9 | ||
| 105 | }; | 109 | }; |
| 106 | 110 | ||
| 111 | #ifdef ACPI_CREATE_PREDEFINED_TABLE | ||
| 107 | /* | 112 | /* |
| 108 | * Predefined method/object information table. | 113 | * Predefined method/object information table. |
| 109 | * | 114 | * |
| @@ -136,239 +141,384 @@ enum acpi_return_package_types { | |||
| 136 | * is saved here (rather than in a separate table) in order to minimize the | 141 | * is saved here (rather than in a separate table) in order to minimize the |
| 137 | * overall size of the stored data. | 142 | * overall size of the stored data. |
| 138 | */ | 143 | */ |
| 139 | static const union acpi_predefined_info predefined_names[] = { | 144 | static const union acpi_predefined_info predefined_names[] = |
| 140 | {.info = {"_AC0", 0, ACPI_RTYPE_INTEGER}}, | 145 | { |
| 141 | {.info = {"_AC1", 0, ACPI_RTYPE_INTEGER}}, | 146 | {{"_AC0", 0, ACPI_RTYPE_INTEGER}}, |
| 142 | {.info = {"_AC2", 0, ACPI_RTYPE_INTEGER}}, | 147 | {{"_AC1", 0, ACPI_RTYPE_INTEGER}}, |
| 143 | {.info = {"_AC3", 0, ACPI_RTYPE_INTEGER}}, | 148 | {{"_AC2", 0, ACPI_RTYPE_INTEGER}}, |
| 144 | {.info = {"_AC4", 0, ACPI_RTYPE_INTEGER}}, | 149 | {{"_AC3", 0, ACPI_RTYPE_INTEGER}}, |
| 145 | {.info = {"_AC5", 0, ACPI_RTYPE_INTEGER}}, | 150 | {{"_AC4", 0, ACPI_RTYPE_INTEGER}}, |
| 146 | {.info = {"_AC6", 0, ACPI_RTYPE_INTEGER}}, | 151 | {{"_AC5", 0, ACPI_RTYPE_INTEGER}}, |
| 147 | {.info = {"_AC7", 0, ACPI_RTYPE_INTEGER}}, | 152 | {{"_AC6", 0, ACPI_RTYPE_INTEGER}}, |
| 148 | {.info = {"_AC8", 0, ACPI_RTYPE_INTEGER}}, | 153 | {{"_AC7", 0, ACPI_RTYPE_INTEGER}}, |
| 149 | {.info = {"_AC9", 0, ACPI_RTYPE_INTEGER}}, | 154 | {{"_AC8", 0, ACPI_RTYPE_INTEGER}}, |
| 150 | {.info = {"_ADR", 0, ACPI_RTYPE_INTEGER}}, | 155 | {{"_AC9", 0, ACPI_RTYPE_INTEGER}}, |
| 151 | {.info = {"_AL0", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 156 | {{"_ADR", 0, ACPI_RTYPE_INTEGER}}, |
| 152 | {.info = {"_AL1", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 157 | {{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 153 | {.info = {"_AL2", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 158 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 154 | {.info = {"_AL3", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 159 | |
| 155 | {.info = {"_AL4", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 160 | {{"_AL1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 156 | {.info = {"_AL5", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 161 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 157 | {.info = {"_AL6", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 162 | |
| 158 | {.info = {"_AL7", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 163 | {{"_AL2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 159 | {.info = {"_AL8", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 164 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 160 | {.info = {"_AL9", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 165 | |
| 161 | {.info = {"_ALC", 0, ACPI_RTYPE_INTEGER}}, | 166 | {{"_AL3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 162 | {.info = {"_ALI", 0, ACPI_RTYPE_INTEGER}}, | 167 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 163 | {.info = {"_ALP", 0, ACPI_RTYPE_INTEGER}}, | 168 | |
| 164 | {.info = {"_ALR", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* variable (Pkgs) each 2 (Ints) */ | 169 | {{"_AL4", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 165 | {.info = {"_ALT", 0, ACPI_RTYPE_INTEGER}}, | 170 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 166 | {.info = {"_BBN", 0, ACPI_RTYPE_INTEGER}}, | 171 | |
| 167 | {.info = {"_BCL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */ | 172 | {{"_AL5", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 168 | {.info = {"_BCM", 1, 0}}, | 173 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 169 | {.info = {"_BDN", 0, ACPI_RTYPE_INTEGER}}, | 174 | |
| 170 | {.info = {"_BFS", 1, 0}}, | 175 | {{"_AL6", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 171 | {.info = {"_BIF", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, | 176 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 172 | 9, | 177 | |
| 173 | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 4, 0}}, /* fixed (9 Int),(4 Str) */ | 178 | {{"_AL7", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 174 | {.info = {"_BLT", 3, 0}}, | 179 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 175 | {.info = {"_BMC", 1, 0}}, | 180 | |
| 176 | {.info = {"_BMD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* fixed (5 Int) */ | 181 | {{"_AL8", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 177 | {.info = {"_BQC", 0, ACPI_RTYPE_INTEGER}}, | 182 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 178 | {.info = {"_BST", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */ | 183 | |
| 179 | {.info = {"_BTM", 1, ACPI_RTYPE_INTEGER}}, | 184 | {{"_AL9", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 180 | {.info = {"_BTP", 1, 0}}, | 185 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 181 | {.info = {"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* see PCI firmware spec 3.0 */ | 186 | |
| 182 | {.info = {"_CID", 0, | 187 | {{"_ALC", 0, ACPI_RTYPE_INTEGER}}, |
| 183 | ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, | 188 | {{"_ALI", 0, ACPI_RTYPE_INTEGER}}, |
| 184 | {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0, 0, 0, 0}}, /* variable (Ints/Strs) */ | 189 | {{"_ALP", 0, ACPI_RTYPE_INTEGER}}, |
| 185 | {.info = {"_CRS", 0, ACPI_RTYPE_BUFFER}}, | 190 | {{"_ALR", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2 (Ints) */ |
| 186 | {.info = {"_CRT", 0, ACPI_RTYPE_INTEGER}}, | 191 | {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, |
| 187 | {.info = {"_CSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (1 Int(n), n-1 Int) */ | 192 | |
| 188 | {.info = {"_CST", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_PKG_COUNT, | 193 | {{"_ALT", 0, ACPI_RTYPE_INTEGER}}, |
| 189 | ACPI_RTYPE_BUFFER, 1, | 194 | {{"_ART", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */ |
| 190 | ACPI_RTYPE_INTEGER, 3, 0}}, /* variable (1 Int(n), n Pkg (1 Buf/3 Int) */ | 195 | {{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, |
| 191 | {.info = {"_DCK", 1, ACPI_RTYPE_INTEGER}}, | 196 | 11, 0}}, |
| 192 | {.info = {"_DCS", 0, ACPI_RTYPE_INTEGER}}, | 197 | |
| 193 | {.info = {"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, | 198 | {{"_BBN", 0, ACPI_RTYPE_INTEGER}}, |
| 194 | {.info = {"_DDN", 0, ACPI_RTYPE_STRING}}, | 199 | {{"_BCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ |
| 195 | {.info = {"_DGS", 0, ACPI_RTYPE_INTEGER}}, | 200 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, |
| 196 | {.info = {"_DIS", 0, 0}}, | 201 | |
| 197 | {.info = {"_DMA", 0, ACPI_RTYPE_BUFFER}}, | 202 | {{"_BCM", 1, 0}}, |
| 198 | {.info = {"_DOD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */ | 203 | {{"_BCT", 1, ACPI_RTYPE_INTEGER}}, |
| 199 | {.info = {"_DOS", 1, 0}}, | 204 | {{"_BDN", 0, ACPI_RTYPE_INTEGER}}, |
| 200 | {.info = {"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */ | 205 | {{"_BFS", 1, 0}}, |
| 201 | {.info = {"_DSS", 1, 0}}, | 206 | {{"_BIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (9 Int),(4 Str) */ |
| 202 | {.info = {"_DSW", 3, 0}}, | 207 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING}, 4,0}}, |
| 203 | {.info = {"_EC_", 0, ACPI_RTYPE_INTEGER}}, | 208 | |
| 204 | {.info = {"_EDL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 209 | {{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */ |
| 205 | {.info = {"_EJ0", 1, 0}}, | 210 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4, |
| 206 | {.info = {"_EJ1", 1, 0}}, | 211 | 0}}, |
| 207 | {.info = {"_EJ2", 1, 0}}, | 212 | |
| 208 | {.info = {"_EJ3", 1, 0}}, | 213 | {{"_BLT", 3, 0}}, |
| 209 | {.info = {"_EJ4", 1, 0}}, | 214 | {{"_BMA", 1, ACPI_RTYPE_INTEGER}}, |
| 210 | {.info = {"_EJD", 0, ACPI_RTYPE_STRING}}, | 215 | {{"_BMC", 1, 0}}, |
| 211 | {.info = {"_FDE", 0, ACPI_RTYPE_BUFFER}}, | 216 | {{"_BMD", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (5 Int) */ |
| 212 | {.info = {"_FDI", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, 0, 0, 0}}, /* fixed (16 Int) */ | 217 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, |
| 213 | {.info = {"_FDM", 1, 0}}, | 218 | |
| 214 | {.info = {"_FIX", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */ | 219 | {{"_BMS", 1, ACPI_RTYPE_INTEGER}}, |
| 215 | {.info = {"_GLK", 0, ACPI_RTYPE_INTEGER}}, | 220 | {{"_BQC", 0, ACPI_RTYPE_INTEGER}}, |
| 216 | {.info = {"_GPD", 0, ACPI_RTYPE_INTEGER}}, | 221 | {{"_BST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ |
| 217 | {.info = {"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */ | 222 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, |
| 218 | {.info = {"_GSB", 0, ACPI_RTYPE_INTEGER}}, | 223 | |
| 219 | {.info = {"_GTF", 0, ACPI_RTYPE_BUFFER}}, | 224 | {{"_BTM", 1, ACPI_RTYPE_INTEGER}}, |
| 220 | {.info = {"_GTM", 0, ACPI_RTYPE_BUFFER}}, | 225 | {{"_BTP", 1, 0}}, |
| 221 | {.info = {"_GTS", 1, 0}}, | 226 | {{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */ |
| 222 | {.info = {"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, | 227 | {{"_CDM", 0, ACPI_RTYPE_INTEGER}}, |
| 223 | {.info = {"_HOT", 0, ACPI_RTYPE_INTEGER}}, | 228 | {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */ |
| 224 | {.info = {"_HPP", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */ | 229 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}}, |
| 230 | |||
| 231 | {{"_CRS", 0, ACPI_RTYPE_BUFFER}}, | ||
| 232 | {{"_CRT", 0, ACPI_RTYPE_INTEGER}}, | ||
| 233 | {{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */ | ||
| 234 | {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, | ||
| 235 | |||
| 236 | {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ | ||
| 237 | {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}}, | ||
| 238 | |||
| 239 | {{"_DCK", 1, ACPI_RTYPE_INTEGER}}, | ||
| 240 | {{"_DCS", 0, ACPI_RTYPE_INTEGER}}, | ||
| 241 | {{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, | ||
| 242 | {{"_DDN", 0, ACPI_RTYPE_STRING}}, | ||
| 243 | {{"_DGS", 0, ACPI_RTYPE_INTEGER}}, | ||
| 244 | {{"_DIS", 0, 0}}, | ||
| 245 | {{"_DMA", 0, ACPI_RTYPE_BUFFER}}, | ||
| 246 | {{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ | ||
| 247 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, | ||
| 248 | |||
| 249 | {{"_DOS", 1, 0}}, | ||
| 250 | {{"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */ | ||
| 251 | {{"_DSS", 1, 0}}, | ||
| 252 | {{"_DSW", 3, 0}}, | ||
| 253 | {{"_DTI", 1, 0}}, | ||
| 254 | {{"_EC_", 0, ACPI_RTYPE_INTEGER}}, | ||
| 255 | {{"_EDL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs)*/ | ||
| 256 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, | ||
| 257 | |||
| 258 | {{"_EJ0", 1, 0}}, | ||
| 259 | {{"_EJ1", 1, 0}}, | ||
| 260 | {{"_EJ2", 1, 0}}, | ||
| 261 | {{"_EJ3", 1, 0}}, | ||
| 262 | {{"_EJ4", 1, 0}}, | ||
| 263 | {{"_EJD", 0, ACPI_RTYPE_STRING}}, | ||
| 264 | {{"_FDE", 0, ACPI_RTYPE_BUFFER}}, | ||
| 265 | {{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */ | ||
| 266 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}}, | ||
| 267 | |||
| 268 | {{"_FDM", 1, 0}}, | ||
| 269 | {{"_FIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ | ||
| 270 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0}, 0, 0}}, | ||
| 271 | |||
| 272 | {{"_FIX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ | ||
| 273 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, | ||
| 274 | |||
| 275 | {{"_FPS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */ | ||
| 276 | {{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 5, 0}, 0, 0}}, | ||
| 277 | |||
| 278 | {{"_FSL", 1, 0}}, | ||
| 279 | {{"_FST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ | ||
| 280 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}}, | ||
| 281 | |||
| 282 | {{"_GAI", 0, ACPI_RTYPE_INTEGER}}, | ||
| 283 | {{"_GHL", 0, ACPI_RTYPE_INTEGER}}, | ||
| 284 | {{"_GLK", 0, ACPI_RTYPE_INTEGER}}, | ||
| 285 | {{"_GPD", 0, ACPI_RTYPE_INTEGER}}, | ||
| 286 | {{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */ | ||
| 287 | {{"_GSB", 0, ACPI_RTYPE_INTEGER}}, | ||
| 288 | {{"_GTF", 0, ACPI_RTYPE_BUFFER}}, | ||
| 289 | {{"_GTM", 0, ACPI_RTYPE_BUFFER}}, | ||
| 290 | {{"_GTS", 1, 0}}, | ||
| 291 | {{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, | ||
| 292 | {{"_HOT", 0, ACPI_RTYPE_INTEGER}}, | ||
| 293 | {{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ | ||
| 294 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, | ||
| 225 | 295 | ||
| 226 | /* | 296 | /* |
| 227 | * For _HPX, a single package is returned, containing a variable number of sub-packages. | 297 | * For _HPX, a single package is returned, containing a Variable-length number |
| 228 | * Each sub-package contains a PCI record setting. There are several different type of | 298 | * of sub-packages. Each sub-package contains a PCI record setting. |
| 229 | * record settings, of different lengths, but all elements of all settings are Integers. | 299 | * There are several different type of record settings, of different |
| 300 | * lengths, but all elements of all settings are Integers. | ||
| 230 | */ | 301 | */ |
| 231 | {.info = {"_HPX", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each (var Ints) */ | 302 | {{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */ |
| 232 | {.info = {"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* see IPMI spec */ | 303 | {{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, |
| 233 | {.info = {"_INI", 0, 0}}, | 304 | |
| 234 | {.info = {"_IRC", 0, 0}}, | 305 | {{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ |
| 235 | {.info = {"_LCK", 1, 0}}, | 306 | {{"_INI", 0, 0}}, |
| 236 | {.info = {"_LID", 0, ACPI_RTYPE_INTEGER}}, | 307 | {{"_IRC", 0, 0}}, |
| 237 | {.info = {"_MAT", 0, ACPI_RTYPE_BUFFER}}, | 308 | {{"_LCK", 1, 0}}, |
| 238 | {.info = {"_MLS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_STRING, 2, 0, 0, 0}}, /* variable (Pkgs) each (2 Str) */ | 309 | {{"_LID", 0, ACPI_RTYPE_INTEGER}}, |
| 239 | {.info = {"_MSG", 1, 0}}, | 310 | {{"_MAT", 0, ACPI_RTYPE_BUFFER}}, |
| 240 | {.info = {"_OFF", 0, 0}}, | 311 | {{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */ |
| 241 | {.info = {"_ON_", 0, 0}}, | 312 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0}, 0, 0}}, |
| 242 | {.info = {"_OS_", 0, ACPI_RTYPE_STRING}}, | 313 | |
| 243 | {.info = {"_OSC", 4, ACPI_RTYPE_BUFFER}}, | 314 | {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */ |
| 244 | {.info = {"_OST", 3, 0}}, | 315 | {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}}, |
| 245 | {.info = {"_PCL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 316 | |
| 246 | {.info = {"_PCT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0}}, /* fixed (2 Buf) */ | 317 | {{"_MSG", 1, 0}}, |
| 247 | {.info = {"_PDC", 1, 0}}, | 318 | {{"_MSM", 4, ACPI_RTYPE_INTEGER}}, |
| 248 | {.info = {"_PIC", 1, 0}}, | 319 | {{"_NTT", 0, ACPI_RTYPE_INTEGER}}, |
| 249 | {.info = {"_PLD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0, 0, 0, 0}}, /* variable (Bufs) */ | 320 | {{"_OFF", 0, 0}}, |
| 250 | {.info = {"_PPC", 0, ACPI_RTYPE_INTEGER}}, | 321 | {{"_ON_", 0, 0}}, |
| 251 | {.info = {"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* see dig64 spec */ | 322 | {{"_OS_", 0, ACPI_RTYPE_STRING}}, |
| 252 | {.info = {"_PR0", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 323 | {{"_OSC", 4, ACPI_RTYPE_BUFFER}}, |
| 253 | {.info = {"_PR1", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 324 | {{"_OST", 3, 0}}, |
| 254 | {.info = {"_PR2", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 325 | {{"_PAI", 1, ACPI_RTYPE_INTEGER}}, |
| 255 | {.info = {"_PRS", 0, ACPI_RTYPE_BUFFER}}, | 326 | {{"_PCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 327 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, | ||
| 328 | |||
| 329 | {{"_PCT", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ | ||
| 330 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, | ||
| 331 | |||
| 332 | {{"_PDC", 1, 0}}, | ||
| 333 | {{"_PDL", 0, ACPI_RTYPE_INTEGER}}, | ||
| 334 | {{"_PIC", 1, 0}}, | ||
| 335 | {{"_PIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int),(3 Str) */ | ||
| 336 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, ACPI_RTYPE_STRING}, 3, 0}}, | ||
| 337 | |||
| 338 | {{"_PLD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Bufs) */ | ||
| 339 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0,0}, 0,0}}, | ||
| 340 | |||
| 341 | {{"_PMC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (11 Int),(3 Str) */ | ||
| 342 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, ACPI_RTYPE_STRING}, 3, | ||
| 343 | 0}}, | ||
| 344 | |||
| 345 | {{"_PMD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 346 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, | ||
| 347 | |||
| 348 | {{"_PMM", 0, ACPI_RTYPE_INTEGER}}, | ||
| 349 | {{"_PPC", 0, ACPI_RTYPE_INTEGER}}, | ||
| 350 | {{"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* See dig64 spec */ | ||
| 351 | {{"_PR0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 352 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, | ||
| 353 | |||
| 354 | {{"_PR1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 355 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, | ||
| 356 | |||
| 357 | {{"_PR2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 358 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, | ||
| 359 | |||
| 360 | {{"_PR3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 361 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, | ||
| 362 | |||
| 363 | {{"_PRL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 364 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, | ||
| 365 | |||
| 366 | {{"_PRS", 0, ACPI_RTYPE_BUFFER}}, | ||
| 256 | 367 | ||
| 257 | /* | 368 | /* |
| 258 | * For _PRT, many BIOSs reverse the 2nd and 3rd Package elements. This bug is so prevalent that there | 369 | * For _PRT, many BIOSs reverse the 3rd and 4th Package elements (Source |
| 259 | * is code in the ACPICA Resource Manager to detect this and switch them back. For now, do not allow | 370 | * and source_index). This bug is so prevalent that there is code in the |
| 260 | * and issue a warning. To allow this and eliminate the warning, add the ACPI_RTYPE_REFERENCE | 371 | * ACPICA Resource Manager to detect this and switch them back. For now, |
| 261 | * type to the 2nd element (index 1) in the statement below. | 372 | * do not allow and issue a warning. To allow this and eliminate the |
| 373 | * warning, add the ACPI_RTYPE_REFERENCE type to the 4th element (index 3) | ||
| 374 | * in the statement below. | ||
| 262 | */ | 375 | */ |
| 263 | {.info = {"_PRT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_FIXED, 4, | 376 | {{"_PRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */ |
| 264 | ACPI_RTYPE_INTEGER, | 377 | {{{ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER,ACPI_RTYPE_INTEGER}, |
| 265 | ACPI_RTYPE_INTEGER, | 378 | ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, |
| 266 | ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, ACPI_RTYPE_INTEGER}}, /* variable (Pkgs) each (4): Int,Int,Int/Ref,Int */ | 379 | ACPI_RTYPE_INTEGER}}, |
| 267 | 380 | ||
| 268 | {.info = {"_PRW", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_OPTION, 2, | 381 | {{"_PRW", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */ |
| 269 | ACPI_RTYPE_INTEGER | | 382 | {{{ACPI_PTYPE1_OPTION, 2, ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE, |
| 270 | ACPI_RTYPE_PACKAGE, | 383 | ACPI_RTYPE_INTEGER}, ACPI_RTYPE_REFERENCE,0}}, |
| 271 | ACPI_RTYPE_INTEGER, ACPI_RTYPE_REFERENCE, 0}}, /* variable (Pkgs) each: Pkg/Int,Int,[variable Refs] (Pkg is Ref/Int) */ | 384 | |
| 272 | 385 | {{"_PS0", 0, 0}}, | |
| 273 | {.info = {"_PS0", 0, 0}}, | 386 | {{"_PS1", 0, 0}}, |
| 274 | {.info = {"_PS1", 0, 0}}, | 387 | {{"_PS2", 0, 0}}, |
| 275 | {.info = {"_PS2", 0, 0}}, | 388 | {{"_PS3", 0, 0}}, |
| 276 | {.info = {"_PS3", 0, 0}}, | 389 | {{"_PSC", 0, ACPI_RTYPE_INTEGER}}, |
| 277 | {.info = {"_PSC", 0, ACPI_RTYPE_INTEGER}}, | 390 | {{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */ |
| 278 | {.info = {"_PSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Pkgs) each (5 Int) with count */ | 391 | {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}}, |
| 279 | {.info = {"_PSL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 392 | |
| 280 | {.info = {"_PSR", 0, ACPI_RTYPE_INTEGER}}, | 393 | {{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ |
| 281 | {.info = {"_PSS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6, 0, 0, 0}}, /* variable (Pkgs) each (6 Int) */ | 394 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, |
| 282 | {.info = {"_PSV", 0, ACPI_RTYPE_INTEGER}}, | 395 | |
| 283 | {.info = {"_PSW", 1, 0}}, | 396 | {{"_PSR", 0, ACPI_RTYPE_INTEGER}}, |
| 284 | {.info = {"_PTC", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0}}, /* fixed (2 Buf) */ | 397 | {{"_PSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (6 Int) */ |
| 285 | {.info = {"_PTS", 1, 0}}, | 398 | {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6,0}, 0,0}}, |
| 286 | {.info = {"_PXM", 0, ACPI_RTYPE_INTEGER}}, | 399 | |
| 287 | {.info = {"_REG", 2, 0}}, | 400 | {{"_PSV", 0, ACPI_RTYPE_INTEGER}}, |
| 288 | {.info = {"_REV", 0, ACPI_RTYPE_INTEGER}}, | 401 | {{"_PSW", 1, 0}}, |
| 289 | {.info = {"_RMV", 0, ACPI_RTYPE_INTEGER}}, | 402 | {{"_PTC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ |
| 290 | {.info = {"_ROM", 2, ACPI_RTYPE_BUFFER}}, | 403 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, |
| 291 | {.info = {"_RTV", 0, ACPI_RTYPE_INTEGER}}, | 404 | |
| 405 | {{"_PTP", 2, ACPI_RTYPE_INTEGER}}, | ||
| 406 | {{"_PTS", 1, 0}}, | ||
| 407 | {{"_PUR", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Int) */ | ||
| 408 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0}, 0, 0}}, | ||
| 409 | |||
| 410 | {{"_PXM", 0, ACPI_RTYPE_INTEGER}}, | ||
| 411 | {{"_REG", 2, 0}}, | ||
| 412 | {{"_REV", 0, ACPI_RTYPE_INTEGER}}, | ||
| 413 | {{"_RMV", 0, ACPI_RTYPE_INTEGER}}, | ||
| 414 | {{"_ROM", 2, ACPI_RTYPE_BUFFER}}, | ||
| 415 | {{"_RTV", 0, ACPI_RTYPE_INTEGER}}, | ||
| 292 | 416 | ||
| 293 | /* | 417 | /* |
| 294 | * For _S0_ through _S5_, the ACPI spec defines a return Package containing 1 Integer, | 418 | * For _S0_ through _S5_, the ACPI spec defines a return Package |
| 295 | * but most DSDTs have it wrong - 2,3, or 4 integers. Allow this by making the objects "variable length", | 419 | * containing 1 Integer, but most DSDTs have it wrong - 2,3, or 4 integers. |
| 296 | * but all elements must be Integers. | 420 | * Allow this by making the objects "Variable-length length", but all elements |
| 421 | * must be Integers. | ||
| 297 | */ | 422 | */ |
| 298 | {.info = {"_S0_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ | 423 | {{"_S0_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ |
| 299 | {.info = {"_S1_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ | 424 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, |
| 300 | {.info = {"_S2_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ | 425 | |
| 301 | {.info = {"_S3_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ | 426 | {{"_S1_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ |
| 302 | {.info = {"_S4_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ | 427 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, |
| 303 | {.info = {"_S5_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ | 428 | |
| 304 | 429 | {{"_S2_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ | |
| 305 | {.info = {"_S1D", 0, ACPI_RTYPE_INTEGER}}, | 430 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, |
| 306 | {.info = {"_S2D", 0, ACPI_RTYPE_INTEGER}}, | 431 | |
| 307 | {.info = {"_S3D", 0, ACPI_RTYPE_INTEGER}}, | 432 | {{"_S3_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ |
| 308 | {.info = {"_S4D", 0, ACPI_RTYPE_INTEGER}}, | 433 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, |
| 309 | {.info = {"_S0W", 0, ACPI_RTYPE_INTEGER}}, | 434 | |
| 310 | {.info = {"_S1W", 0, ACPI_RTYPE_INTEGER}}, | 435 | {{"_S4_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ |
| 311 | {.info = {"_S2W", 0, ACPI_RTYPE_INTEGER}}, | 436 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, |
| 312 | {.info = {"_S3W", 0, ACPI_RTYPE_INTEGER}}, | 437 | |
| 313 | {.info = {"_S4W", 0, ACPI_RTYPE_INTEGER}}, | 438 | {{"_S5_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ |
| 314 | {.info = {"_SBS", 0, ACPI_RTYPE_INTEGER}}, | 439 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, |
| 315 | {.info = {"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */ | 440 | |
| 316 | /* Note: the 3-arg definition may be removed for ACPI 4.0 */ | 441 | {{"_S1D", 0, ACPI_RTYPE_INTEGER}}, |
| 317 | {.info = {"_SDD", 1, 0}}, | 442 | {{"_S2D", 0, ACPI_RTYPE_INTEGER}}, |
| 318 | {.info = {"_SEG", 0, ACPI_RTYPE_INTEGER}}, | 443 | {{"_S3D", 0, ACPI_RTYPE_INTEGER}}, |
| 319 | {.info = {"_SLI", 0, ACPI_RTYPE_BUFFER}}, | 444 | {{"_S4D", 0, ACPI_RTYPE_INTEGER}}, |
| 320 | {.info = {"_SPD", 1, ACPI_RTYPE_INTEGER}}, | 445 | {{"_S0W", 0, ACPI_RTYPE_INTEGER}}, |
| 321 | {.info = {"_SRS", 1, 0}}, | 446 | {{"_S1W", 0, ACPI_RTYPE_INTEGER}}, |
| 322 | {.info = {"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* see IPMI spec */ | 447 | {{"_S2W", 0, ACPI_RTYPE_INTEGER}}, |
| 323 | {.info = {"_SST", 1, 0}}, | 448 | {{"_S3W", 0, ACPI_RTYPE_INTEGER}}, |
| 324 | {.info = {"_STA", 0, ACPI_RTYPE_INTEGER}}, | 449 | {{"_S4W", 0, ACPI_RTYPE_INTEGER}}, |
| 325 | {.info = {"_STM", 3, 0}}, | 450 | {{"_SBS", 0, ACPI_RTYPE_INTEGER}}, |
| 326 | {.info = {"_STR", 0, ACPI_RTYPE_BUFFER}}, | 451 | {{"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */ |
| 327 | {.info = {"_SUN", 0, ACPI_RTYPE_INTEGER}}, | 452 | /* Note: the 3-arg definition may be removed for ACPI 4.0 */ |
| 328 | {.info = {"_SWS", 0, ACPI_RTYPE_INTEGER}}, | 453 | {{"_SDD", 1, 0}}, |
| 329 | {.info = {"_TC1", 0, ACPI_RTYPE_INTEGER}}, | 454 | {{"_SEG", 0, ACPI_RTYPE_INTEGER}}, |
| 330 | {.info = {"_TC2", 0, ACPI_RTYPE_INTEGER}}, | 455 | {{"_SHL", 1, ACPI_RTYPE_INTEGER}}, |
| 331 | {.info = {"_TMP", 0, ACPI_RTYPE_INTEGER}}, | 456 | {{"_SLI", 0, ACPI_RTYPE_BUFFER}}, |
| 332 | {.info = {"_TPC", 0, ACPI_RTYPE_INTEGER}}, | 457 | {{"_SPD", 1, ACPI_RTYPE_INTEGER}}, |
| 333 | {.info = {"_TPT", 1, 0}}, | 458 | {{"_SRS", 1, 0}}, |
| 334 | {.info = {"_TRT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, | 459 | {{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ |
| 335 | ACPI_RTYPE_INTEGER, 6, 0}}, /* variable (Pkgs) each 2_ref/6_int */ | 460 | {{"_SST", 1, 0}}, |
| 336 | {.info = {"_TSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each 5_int with count */ | 461 | {{"_STA", 0, ACPI_RTYPE_INTEGER}}, |
| 337 | {.info = {"_TSP", 0, ACPI_RTYPE_INTEGER}}, | 462 | {{"_STM", 3, 0}}, |
| 338 | {.info = {"_TSS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each 5_int */ | 463 | {{"_STP", 2, ACPI_RTYPE_INTEGER}}, |
| 339 | {.info = {"_TST", 0, ACPI_RTYPE_INTEGER}}, | 464 | {{"_STR", 0, ACPI_RTYPE_BUFFER}}, |
| 340 | {.info = {"_TTS", 1, 0}}, | 465 | {{"_STV", 2, ACPI_RTYPE_INTEGER}}, |
| 341 | {.info = {"_TZD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ | 466 | {{"_SUN", 0, ACPI_RTYPE_INTEGER}}, |
| 342 | {.info = {"_TZM", 0, ACPI_RTYPE_REFERENCE}}, | 467 | {{"_SWS", 0, ACPI_RTYPE_INTEGER}}, |
| 343 | {.info = {"_TZP", 0, ACPI_RTYPE_INTEGER}}, | 468 | {{"_TC1", 0, ACPI_RTYPE_INTEGER}}, |
| 344 | {.info = {"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, | 469 | {{"_TC2", 0, ACPI_RTYPE_INTEGER}}, |
| 345 | {.info = {"_UPC", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */ | 470 | {{"_TIP", 1, ACPI_RTYPE_INTEGER}}, |
| 346 | {.info = {"_UPD", 0, ACPI_RTYPE_INTEGER}}, | 471 | {{"_TIV", 1, ACPI_RTYPE_INTEGER}}, |
| 347 | {.info = {"_UPP", 0, ACPI_RTYPE_INTEGER}}, | 472 | {{"_TMP", 0, ACPI_RTYPE_INTEGER}}, |
| 348 | {.info = {"_VPO", 0, ACPI_RTYPE_INTEGER}}, | 473 | {{"_TPC", 0, ACPI_RTYPE_INTEGER}}, |
| 474 | {{"_TPT", 1, 0}}, | ||
| 475 | {{"_TRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2_ref/6_int */ | ||
| 476 | {{{ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, 6, 0}}, | ||
| 477 | |||
| 478 | {{"_TSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int with count */ | ||
| 479 | {{{ACPI_PTYPE2_COUNT,ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, | ||
| 480 | |||
| 481 | {{"_TSP", 0, ACPI_RTYPE_INTEGER}}, | ||
| 482 | {{"_TSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int */ | ||
| 483 | {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, | ||
| 484 | |||
| 485 | {{"_TST", 0, ACPI_RTYPE_INTEGER}}, | ||
| 486 | {{"_TTS", 1, 0}}, | ||
| 487 | {{"_TZD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ | ||
| 488 | {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, | ||
| 489 | |||
| 490 | {{"_TZM", 0, ACPI_RTYPE_REFERENCE}}, | ||
| 491 | {{"_TZP", 0, ACPI_RTYPE_INTEGER}}, | ||
| 492 | {{"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, | ||
| 493 | {{"_UPC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ | ||
| 494 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, | ||
| 495 | |||
| 496 | {{"_UPD", 0, ACPI_RTYPE_INTEGER}}, | ||
| 497 | {{"_UPP", 0, ACPI_RTYPE_INTEGER}}, | ||
| 498 | {{"_VPO", 0, ACPI_RTYPE_INTEGER}}, | ||
| 349 | 499 | ||
| 350 | /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ | 500 | /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ |
| 351 | 501 | ||
| 352 | {.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, | 502 | {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, |
| 353 | {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* fixed (2 Int), but is optional */ | 503 | {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */ |
| 354 | {.ret_info = {0, 0, 0, 0, 0, 0}} /* Table terminator */ | 504 | |
| 505 | {{{0,0,0,0}, 0,0}} /* Table terminator */ | ||
| 355 | }; | 506 | }; |
| 356 | 507 | ||
| 357 | #if 0 | 508 | #if 0 |
| 358 | /* Not implemented */ | 509 | /* Not implemented */ |
| 359 | 510 | ||
| 360 | { | 511 | {{"_WDG", 0, ACPI_RTYPE_BUFFER}}, /* MS Extension */ |
| 361 | "_WDG", 0, ACPI_RTYPE_BUFFER}, /* MS Extension */ | 512 | {{"_WED", 1, ACPI_RTYPE_PACKAGE}}, /* MS Extension */ |
| 362 | 513 | ||
| 363 | { | 514 | /* This is an internally implemented control method, no need to check */ |
| 364 | "_WED", 1, ACPI_RTYPE_PACKAGE}, /* MS Extension */ | 515 | {{"_OSI", 1, ACPI_RTYPE_INTEGER}}, |
| 365 | 516 | ||
| 366 | /* This is an internally implemented control method, no need to check */ | 517 | /* TBD: */ |
| 367 | { | 518 | |
| 368 | "_OSI", 1, ACPI_RTYPE_INTEGER}, | 519 | _PRT - currently ignore reversed entries. attempt to fix here? |
| 520 | think about possibly fixing package elements like _BIF, etc. | ||
| 521 | #endif | ||
| 369 | 522 | ||
| 370 | /* TBD: */ | ||
| 371 | _PRT - currently ignore reversed entries.attempt to fix here ? | ||
| 372 | think about code that attempts to fix package elements like _BIF, etc. | ||
| 373 | #endif | 523 | #endif |
| 374 | #endif | 524 | #endif |
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 897810ba0ccc..863a264b829e 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h | |||
| @@ -324,26 +324,30 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
| 324 | acpi_status | 324 | acpi_status |
| 325 | acpi_ut_evaluate_numeric_object(char *object_name, | 325 | acpi_ut_evaluate_numeric_object(char *object_name, |
| 326 | struct acpi_namespace_node *device_node, | 326 | struct acpi_namespace_node *device_node, |
| 327 | acpi_integer * address); | 327 | acpi_integer *value); |
| 328 | 328 | ||
| 329 | acpi_status | 329 | acpi_status |
| 330 | acpi_ut_execute_HID(struct acpi_namespace_node *device_node, | 330 | acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 *status_flags); |
| 331 | struct acpica_device_id *hid); | ||
| 332 | 331 | ||
| 333 | acpi_status | 332 | acpi_status |
| 334 | acpi_ut_execute_CID(struct acpi_namespace_node *device_node, | 333 | acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, |
| 335 | struct acpi_compatible_id_list **return_cid_list); | 334 | const char **method_names, |
| 335 | u8 method_count, u8 *out_values); | ||
| 336 | 336 | ||
| 337 | /* | ||
| 338 | * utids - device ID support | ||
| 339 | */ | ||
| 337 | acpi_status | 340 | acpi_status |
| 338 | acpi_ut_execute_STA(struct acpi_namespace_node *device_node, | 341 | acpi_ut_execute_HID(struct acpi_namespace_node *device_node, |
| 339 | u32 * status_flags); | 342 | struct acpica_device_id **return_id); |
| 340 | 343 | ||
| 341 | acpi_status | 344 | acpi_status |
| 342 | acpi_ut_execute_UID(struct acpi_namespace_node *device_node, | 345 | acpi_ut_execute_UID(struct acpi_namespace_node *device_node, |
| 343 | struct acpica_device_id *uid); | 346 | struct acpica_device_id **return_id); |
| 344 | 347 | ||
| 345 | acpi_status | 348 | acpi_status |
| 346 | acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest); | 349 | acpi_ut_execute_CID(struct acpi_namespace_node *device_node, |
| 350 | struct acpica_device_id_list **return_cid_list); | ||
| 347 | 351 | ||
| 348 | /* | 352 | /* |
| 349 | * utlock - reader/writer locks | 353 | * utlock - reader/writer locks |
| @@ -445,6 +449,8 @@ acpi_ut_short_divide(acpi_integer in_dividend, | |||
| 445 | */ | 449 | */ |
| 446 | const char *acpi_ut_validate_exception(acpi_status status); | 450 | const char *acpi_ut_validate_exception(acpi_status status); |
| 447 | 451 | ||
| 452 | u8 acpi_ut_is_pci_root_bridge(char *id); | ||
| 453 | |||
| 448 | u8 acpi_ut_is_aml_table(struct acpi_table_header *table); | 454 | u8 acpi_ut_is_aml_table(struct acpi_table_header *table); |
| 449 | 455 | ||
| 450 | acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); | 456 | acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); |
| @@ -469,6 +475,12 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position); | |||
| 469 | acpi_status | 475 | acpi_status |
| 470 | acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); | 476 | acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); |
| 471 | 477 | ||
| 478 | void ACPI_INTERNAL_VAR_XFACE | ||
| 479 | acpi_ut_predefined_warning(const char *module_name, | ||
| 480 | u32 line_number, | ||
| 481 | char *pathname, | ||
| 482 | u8 node_flags, const char *format, ...); | ||
| 483 | |||
| 472 | /* Values for Base above (16=Hex, 10=Decimal) */ | 484 | /* Values for Base above (16=Hex, 10=Decimal) */ |
| 473 | 485 | ||
| 474 | #define ACPI_ANY_BASE 0 | 486 | #define ACPI_ANY_BASE 0 |
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index 067f967eb389..4940249f2524 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h | |||
| @@ -404,6 +404,7 @@ typedef enum { | |||
| 404 | REGION_SMBUS, | 404 | REGION_SMBUS, |
| 405 | REGION_CMOS, | 405 | REGION_CMOS, |
| 406 | REGION_PCI_BAR, | 406 | REGION_PCI_BAR, |
| 407 | REGION_IPMI, | ||
| 407 | REGION_DATA_TABLE, /* Internal use only */ | 408 | REGION_DATA_TABLE, /* Internal use only */ |
| 408 | REGION_FIXED_HW = 0x7F | 409 | REGION_FIXED_HW = 0x7F |
| 409 | } AML_REGION_TYPES; | 410 | } AML_REGION_TYPES; |
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 53e27bc5a734..54a225e56a64 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c | |||
| @@ -123,9 +123,12 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
| 123 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | 123 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
| 124 | ACPI_NS_ERROR_IF_FOUND; | 124 | ACPI_NS_ERROR_IF_FOUND; |
| 125 | 125 | ||
| 126 | /* Mark node temporary if we are executing a method */ | 126 | /* |
| 127 | 127 | * Mark node temporary if we are executing a normal control | |
| 128 | if (walk_state->method_node) { | 128 | * method. (Don't mark if this is a module-level code method) |
| 129 | */ | ||
| 130 | if (walk_state->method_node && | ||
| 131 | !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
| 129 | flags |= ACPI_NS_TEMPORARY; | 132 | flags |= ACPI_NS_TEMPORARY; |
| 130 | } | 133 | } |
| 131 | 134 | ||
| @@ -456,9 +459,12 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
| 456 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | 459 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
| 457 | ACPI_NS_ERROR_IF_FOUND; | 460 | ACPI_NS_ERROR_IF_FOUND; |
| 458 | 461 | ||
| 459 | /* Mark node(s) temporary if we are executing a method */ | 462 | /* |
| 460 | 463 | * Mark node(s) temporary if we are executing a normal control | |
| 461 | if (walk_state->method_node) { | 464 | * method. (Don't mark if this is a module-level code method) |
| 465 | */ | ||
| 466 | if (walk_state->method_node && | ||
| 467 | !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
| 462 | flags |= ACPI_NS_TEMPORARY; | 468 | flags |= ACPI_NS_TEMPORARY; |
| 463 | } | 469 | } |
| 464 | 470 | ||
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 14b8b8ed8023..567a4899a018 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c | |||
| @@ -578,10 +578,15 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | /* | 580 | /* |
| 581 | * Delete any namespace objects created anywhere within | 581 | * Delete any namespace objects created anywhere within the |
| 582 | * the namespace by the execution of this method | 582 | * namespace by the execution of this method. Unless this method |
| 583 | * is a module-level executable code method, in which case we | ||
| 584 | * want make the objects permanent. | ||
| 583 | */ | 585 | */ |
| 584 | acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); | 586 | if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { |
| 587 | acpi_ns_delete_namespace_by_owner(method_desc->method. | ||
| 588 | owner_id); | ||
| 589 | } | ||
| 585 | } | 590 | } |
| 586 | 591 | ||
| 587 | /* Decrement the thread count on the method */ | 592 | /* Decrement the thread count on the method */ |
| @@ -622,7 +627,9 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
| 622 | 627 | ||
| 623 | /* No more threads, we can free the owner_id */ | 628 | /* No more threads, we can free the owner_id */ |
| 624 | 629 | ||
| 625 | acpi_ut_release_owner_id(&method_desc->method.owner_id); | 630 | if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { |
| 631 | acpi_ut_release_owner_id(&method_desc->method.owner_id); | ||
| 632 | } | ||
| 626 | } | 633 | } |
| 627 | 634 | ||
| 628 | return_VOID; | 635 | return_VOID; |
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 22b1a3ce2c94..7d077bb2f525 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c | |||
| @@ -433,10 +433,10 @@ acpi_ds_method_data_get_value(u8 type, | |||
| 433 | 433 | ||
| 434 | case ACPI_REFCLASS_LOCAL: | 434 | case ACPI_REFCLASS_LOCAL: |
| 435 | 435 | ||
| 436 | ACPI_ERROR((AE_INFO, | 436 | /* |
| 437 | "Uninitialized Local[%d] at node %p", | 437 | * No error message for this case, will be trapped again later to |
| 438 | index, node)); | 438 | * detect and ignore cases of Store(local_x,local_x) |
| 439 | 439 | */ | |
| 440 | return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); | 440 | return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); |
| 441 | 441 | ||
| 442 | default: | 442 | default: |
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 02e6caad4a76..507e1f0bbdfd 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c | |||
| @@ -482,14 +482,27 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 482 | if (arg) { | 482 | if (arg) { |
| 483 | /* | 483 | /* |
| 484 | * num_elements was exhausted, but there are remaining elements in the | 484 | * num_elements was exhausted, but there are remaining elements in the |
| 485 | * package_list. | 485 | * package_list. Truncate the package to num_elements. |
| 486 | * | 486 | * |
| 487 | * Note: technically, this is an error, from ACPI spec: "It is an error | 487 | * Note: technically, this is an error, from ACPI spec: "It is an error |
| 488 | * for NumElements to be less than the number of elements in the | 488 | * for NumElements to be less than the number of elements in the |
| 489 | * PackageList". However, for now, we just print an error message and | 489 | * PackageList". However, we just print an error message and |
| 490 | * no exception is returned. | 490 | * no exception is returned. This provides Windows compatibility. Some |
| 491 | * BIOSs will alter the num_elements on the fly, creating this type | ||
| 492 | * of ill-formed package object. | ||
| 491 | */ | 493 | */ |
| 492 | while (arg) { | 494 | while (arg) { |
| 495 | /* | ||
| 496 | * We must delete any package elements that were created earlier | ||
| 497 | * and are not going to be used because of the package truncation. | ||
| 498 | */ | ||
| 499 | if (arg->common.node) { | ||
| 500 | acpi_ut_remove_reference(ACPI_CAST_PTR | ||
| 501 | (union | ||
| 502 | acpi_operand_object, | ||
| 503 | arg->common.node)); | ||
| 504 | arg->common.node = NULL; | ||
| 505 | } | ||
| 493 | 506 | ||
| 494 | /* Find out how many elements there really are */ | 507 | /* Find out how many elements there really are */ |
| 495 | 508 | ||
| @@ -498,7 +511,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 498 | } | 511 | } |
| 499 | 512 | ||
| 500 | ACPI_WARNING((AE_INFO, | 513 | ACPI_WARNING((AE_INFO, |
| 501 | "Package List length (%X) larger than NumElements count (%X), truncated\n", | 514 | "Package List length (0x%X) larger than NumElements count (0x%X), truncated\n", |
| 502 | i, element_count)); | 515 | i, element_count)); |
| 503 | } else if (i < element_count) { | 516 | } else if (i < element_count) { |
| 504 | /* | 517 | /* |
| @@ -506,7 +519,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 506 | * Note: this is not an error, the package is padded out with NULLs. | 519 | * Note: this is not an error, the package is padded out with NULLs. |
| 507 | */ | 520 | */ |
| 508 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 521 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 509 | "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", | 522 | "Package List length (0x%X) smaller than NumElements count (0x%X), padded with null elements\n", |
| 510 | i, element_count)); | 523 | i, element_count)); |
| 511 | } | 524 | } |
| 512 | 525 | ||
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 3023ceaa8d54..6de3a99d4cd4 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c | |||
| @@ -581,21 +581,6 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | |||
| 581 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && | 581 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && |
| 582 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || | 582 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || |
| 583 | (!(walk_state->op_info->flags & AML_NAMED))) { | 583 | (!(walk_state->op_info->flags & AML_NAMED))) { |
| 584 | #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE | ||
| 585 | if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || | ||
| 586 | (walk_state->op_info->class == AML_CLASS_CONTROL)) { | ||
| 587 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
| 588 | "Begin/EXEC: %s (fl %8.8X)\n", | ||
| 589 | walk_state->op_info->name, | ||
| 590 | walk_state->op_info->flags)); | ||
| 591 | |||
| 592 | /* Executing a type1 or type2 opcode outside of a method */ | ||
| 593 | |||
| 594 | status = | ||
| 595 | acpi_ds_exec_begin_op(walk_state, out_op); | ||
| 596 | return_ACPI_STATUS(status); | ||
| 597 | } | ||
| 598 | #endif | ||
| 599 | return_ACPI_STATUS(AE_OK); | 584 | return_ACPI_STATUS(AE_OK); |
| 600 | } | 585 | } |
| 601 | 586 | ||
| @@ -768,7 +753,13 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | |||
| 768 | 753 | ||
| 769 | /* Execution mode, node cannot already exist, node is temporary */ | 754 | /* Execution mode, node cannot already exist, node is temporary */ |
| 770 | 755 | ||
| 771 | flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); | 756 | flags |= ACPI_NS_ERROR_IF_FOUND; |
| 757 | |||
| 758 | if (! | ||
| 759 | (walk_state-> | ||
| 760 | parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
| 761 | flags |= ACPI_NS_TEMPORARY; | ||
| 762 | } | ||
| 772 | } | 763 | } |
| 773 | 764 | ||
| 774 | /* Add new entry or lookup existing entry */ | 765 | /* Add new entry or lookup existing entry */ |
| @@ -851,24 +842,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
| 851 | /* Check if opcode had an associated namespace object */ | 842 | /* Check if opcode had an associated namespace object */ |
| 852 | 843 | ||
| 853 | if (!(walk_state->op_info->flags & AML_NSOBJECT)) { | 844 | if (!(walk_state->op_info->flags & AML_NSOBJECT)) { |
| 854 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
| 855 | #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE | ||
| 856 | /* No namespace object. Executable opcode? */ | ||
| 857 | |||
| 858 | if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || | ||
| 859 | (walk_state->op_info->class == AML_CLASS_CONTROL)) { | ||
| 860 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
| 861 | "End/EXEC: %s (fl %8.8X)\n", | ||
| 862 | walk_state->op_info->name, | ||
| 863 | walk_state->op_info->flags)); | ||
| 864 | |||
| 865 | /* Executing a type1 or type2 opcode outside of a method */ | ||
| 866 | |||
| 867 | status = acpi_ds_exec_end_op(walk_state); | ||
| 868 | return_ACPI_STATUS(status); | ||
| 869 | } | ||
| 870 | #endif | ||
| 871 | #endif | ||
| 872 | return_ACPI_STATUS(AE_OK); | 845 | return_ACPI_STATUS(AE_OK); |
| 873 | } | 846 | } |
| 874 | 847 | ||
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index b9d8ee69ca6c..afacf4416c73 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
| @@ -424,8 +424,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
| 424 | /* Read the Status Register */ | 424 | /* Read the Status Register */ |
| 425 | 425 | ||
| 426 | status = | 426 | status = |
| 427 | acpi_read(&status_reg, | 427 | acpi_hw_read(&status_reg, |
| 428 | &gpe_register_info->status_address); | 428 | &gpe_register_info->status_address); |
| 429 | if (ACPI_FAILURE(status)) { | 429 | if (ACPI_FAILURE(status)) { |
| 430 | goto unlock_and_exit; | 430 | goto unlock_and_exit; |
| 431 | } | 431 | } |
| @@ -433,8 +433,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
| 433 | /* Read the Enable Register */ | 433 | /* Read the Enable Register */ |
| 434 | 434 | ||
| 435 | status = | 435 | status = |
| 436 | acpi_read(&enable_reg, | 436 | acpi_hw_read(&enable_reg, |
| 437 | &gpe_register_info->enable_address); | 437 | &gpe_register_info->enable_address); |
| 438 | if (ACPI_FAILURE(status)) { | 438 | if (ACPI_FAILURE(status)) { |
| 439 | goto unlock_and_exit; | 439 | goto unlock_and_exit; |
| 440 | } | 440 | } |
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 7b3463639422..a60aaa7635f3 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
| @@ -843,14 +843,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) | |||
| 843 | 843 | ||
| 844 | /* Disable all GPEs within this register */ | 844 | /* Disable all GPEs within this register */ |
| 845 | 845 | ||
| 846 | status = acpi_write(0x00, &this_register->enable_address); | 846 | status = acpi_hw_write(0x00, &this_register->enable_address); |
| 847 | if (ACPI_FAILURE(status)) { | 847 | if (ACPI_FAILURE(status)) { |
| 848 | goto error_exit; | 848 | goto error_exit; |
| 849 | } | 849 | } |
| 850 | 850 | ||
| 851 | /* Clear any pending GPE events within this register */ | 851 | /* Clear any pending GPE events within this register */ |
| 852 | 852 | ||
| 853 | status = acpi_write(0xFF, &this_register->status_address); | 853 | status = acpi_hw_write(0xFF, &this_register->status_address); |
| 854 | if (ACPI_FAILURE(status)) { | 854 | if (ACPI_FAILURE(status)) { |
| 855 | goto error_exit; | 855 | goto error_exit; |
| 856 | } | 856 | } |
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 284a7becbe96..cf29c4953028 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c | |||
| @@ -50,8 +50,6 @@ | |||
| 50 | ACPI_MODULE_NAME("evrgnini") | 50 | ACPI_MODULE_NAME("evrgnini") |
| 51 | 51 | ||
| 52 | /* Local prototypes */ | 52 | /* Local prototypes */ |
| 53 | static u8 acpi_ev_match_pci_root_bridge(char *id); | ||
| 54 | |||
| 55 | static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); | 53 | static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); |
| 56 | 54 | ||
| 57 | /******************************************************************************* | 55 | /******************************************************************************* |
| @@ -332,37 +330,6 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
| 332 | 330 | ||
| 333 | /******************************************************************************* | 331 | /******************************************************************************* |
| 334 | * | 332 | * |
| 335 | * FUNCTION: acpi_ev_match_pci_root_bridge | ||
| 336 | * | ||
| 337 | * PARAMETERS: Id - The HID/CID in string format | ||
| 338 | * | ||
| 339 | * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge | ||
| 340 | * | ||
| 341 | * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. | ||
| 342 | * | ||
| 343 | ******************************************************************************/ | ||
| 344 | |||
| 345 | static u8 acpi_ev_match_pci_root_bridge(char *id) | ||
| 346 | { | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Check if this is a PCI root. | ||
| 350 | * ACPI 3.0+: check for a PCI Express root also. | ||
| 351 | */ | ||
| 352 | if (!(ACPI_STRNCMP(id, | ||
| 353 | PCI_ROOT_HID_STRING, | ||
| 354 | sizeof(PCI_ROOT_HID_STRING))) || | ||
| 355 | !(ACPI_STRNCMP(id, | ||
| 356 | PCI_EXPRESS_ROOT_HID_STRING, | ||
| 357 | sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { | ||
| 358 | return (TRUE); | ||
| 359 | } | ||
| 360 | |||
| 361 | return (FALSE); | ||
| 362 | } | ||
| 363 | |||
| 364 | /******************************************************************************* | ||
| 365 | * | ||
| 366 | * FUNCTION: acpi_ev_is_pci_root_bridge | 333 | * FUNCTION: acpi_ev_is_pci_root_bridge |
| 367 | * | 334 | * |
| 368 | * PARAMETERS: Node - Device node being examined | 335 | * PARAMETERS: Node - Device node being examined |
| @@ -377,9 +344,10 @@ static u8 acpi_ev_match_pci_root_bridge(char *id) | |||
| 377 | static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) | 344 | static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) |
| 378 | { | 345 | { |
| 379 | acpi_status status; | 346 | acpi_status status; |
| 380 | struct acpica_device_id hid; | 347 | struct acpica_device_id *hid; |
| 381 | struct acpi_compatible_id_list *cid; | 348 | struct acpica_device_id_list *cid; |
| 382 | u32 i; | 349 | u32 i; |
| 350 | u8 match; | ||
| 383 | 351 | ||
| 384 | /* Get the _HID and check for a PCI Root Bridge */ | 352 | /* Get the _HID and check for a PCI Root Bridge */ |
| 385 | 353 | ||
| @@ -388,7 +356,10 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) | |||
| 388 | return (FALSE); | 356 | return (FALSE); |
| 389 | } | 357 | } |
| 390 | 358 | ||
| 391 | if (acpi_ev_match_pci_root_bridge(hid.value)) { | 359 | match = acpi_ut_is_pci_root_bridge(hid->string); |
| 360 | ACPI_FREE(hid); | ||
| 361 | |||
| 362 | if (match) { | ||
| 392 | return (TRUE); | 363 | return (TRUE); |
| 393 | } | 364 | } |
| 394 | 365 | ||
| @@ -402,7 +373,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) | |||
| 402 | /* Check all _CIDs in the returned list */ | 373 | /* Check all _CIDs in the returned list */ |
| 403 | 374 | ||
| 404 | for (i = 0; i < cid->count; i++) { | 375 | for (i = 0; i < cid->count; i++) { |
| 405 | if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { | 376 | if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) { |
| 406 | ACPI_FREE(cid); | 377 | ACPI_FREE(cid); |
| 407 | return (TRUE); | 378 | return (TRUE); |
| 408 | } | 379 | } |
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 277fd609611a..24afef81af39 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c | |||
| @@ -110,8 +110,15 @@ acpi_ex_add_table(u32 table_index, | |||
| 110 | if (ACPI_FAILURE(status)) { | 110 | if (ACPI_FAILURE(status)) { |
| 111 | acpi_ut_remove_reference(obj_desc); | 111 | acpi_ut_remove_reference(obj_desc); |
| 112 | *ddb_handle = NULL; | 112 | *ddb_handle = NULL; |
| 113 | return_ACPI_STATUS(status); | ||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 116 | /* Execute any module-level code that was found in the table */ | ||
| 117 | |||
| 118 | acpi_ex_exit_interpreter(); | ||
| 119 | acpi_ns_exec_module_code_list(); | ||
| 120 | acpi_ex_enter_interpreter(); | ||
| 121 | |||
| 115 | return_ACPI_STATUS(status); | 122 | return_ACPI_STATUS(status); |
| 116 | } | 123 | } |
| 117 | 124 | ||
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index ec524614e708..de3446372ddc 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c | |||
| @@ -418,9 +418,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, | |||
| 418 | case ACPI_EXD_REFERENCE: | 418 | case ACPI_EXD_REFERENCE: |
| 419 | 419 | ||
| 420 | acpi_ex_out_string("Class Name", | 420 | acpi_ex_out_string("Class Name", |
| 421 | (char *) | 421 | ACPI_CAST_PTR(char, |
| 422 | acpi_ut_get_reference_name | 422 | acpi_ut_get_reference_name |
| 423 | (obj_desc)); | 423 | (obj_desc))); |
| 424 | acpi_ex_dump_reference_obj(obj_desc); | 424 | acpi_ex_dump_reference_obj(obj_desc); |
| 425 | break; | 425 | break; |
| 426 | 426 | ||
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 546dcdd86785..0b33d6c887b9 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c | |||
| @@ -72,6 +72,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
| 72 | union acpi_operand_object *buffer_desc; | 72 | union acpi_operand_object *buffer_desc; |
| 73 | acpi_size length; | 73 | acpi_size length; |
| 74 | void *buffer; | 74 | void *buffer; |
| 75 | u32 function; | ||
| 75 | 76 | ||
| 76 | ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); | 77 | ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); |
| 77 | 78 | ||
| @@ -97,13 +98,27 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
| 97 | } | 98 | } |
| 98 | } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && | 99 | } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && |
| 99 | (obj_desc->field.region_obj->region.space_id == | 100 | (obj_desc->field.region_obj->region.space_id == |
| 100 | ACPI_ADR_SPACE_SMBUS)) { | 101 | ACPI_ADR_SPACE_SMBUS |
| 102 | || obj_desc->field.region_obj->region.space_id == | ||
| 103 | ACPI_ADR_SPACE_IPMI)) { | ||
| 101 | /* | 104 | /* |
| 102 | * This is an SMBus read. We must create a buffer to hold the data | 105 | * This is an SMBus or IPMI read. We must create a buffer to hold |
| 103 | * and directly access the region handler. | 106 | * the data and then directly access the region handler. |
| 107 | * | ||
| 108 | * Note: Smbus protocol value is passed in upper 16-bits of Function | ||
| 104 | */ | 109 | */ |
| 105 | buffer_desc = | 110 | if (obj_desc->field.region_obj->region.space_id == |
| 106 | acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); | 111 | ACPI_ADR_SPACE_SMBUS) { |
| 112 | length = ACPI_SMBUS_BUFFER_SIZE; | ||
| 113 | function = | ||
| 114 | ACPI_READ | (obj_desc->field.attribute << 16); | ||
| 115 | } else { /* IPMI */ | ||
| 116 | |||
| 117 | length = ACPI_IPMI_BUFFER_SIZE; | ||
| 118 | function = ACPI_READ; | ||
| 119 | } | ||
| 120 | |||
| 121 | buffer_desc = acpi_ut_create_buffer_object(length); | ||
| 107 | if (!buffer_desc) { | 122 | if (!buffer_desc) { |
| 108 | return_ACPI_STATUS(AE_NO_MEMORY); | 123 | return_ACPI_STATUS(AE_NO_MEMORY); |
| 109 | } | 124 | } |
| @@ -112,16 +127,13 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
| 112 | 127 | ||
| 113 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); | 128 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); |
| 114 | 129 | ||
| 115 | /* | 130 | /* Call the region handler for the read */ |
| 116 | * Perform the read. | 131 | |
| 117 | * Note: Smbus protocol value is passed in upper 16-bits of Function | ||
| 118 | */ | ||
| 119 | status = acpi_ex_access_region(obj_desc, 0, | 132 | status = acpi_ex_access_region(obj_desc, 0, |
| 120 | ACPI_CAST_PTR(acpi_integer, | 133 | ACPI_CAST_PTR(acpi_integer, |
| 121 | buffer_desc-> | 134 | buffer_desc-> |
| 122 | buffer.pointer), | 135 | buffer.pointer), |
| 123 | ACPI_READ | (obj_desc->field. | 136 | function); |
| 124 | attribute << 16)); | ||
| 125 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); | 137 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
| 126 | goto exit; | 138 | goto exit; |
| 127 | } | 139 | } |
| @@ -212,6 +224,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
| 212 | u32 length; | 224 | u32 length; |
| 213 | void *buffer; | 225 | void *buffer; |
| 214 | union acpi_operand_object *buffer_desc; | 226 | union acpi_operand_object *buffer_desc; |
| 227 | u32 function; | ||
| 215 | 228 | ||
| 216 | ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); | 229 | ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); |
| 217 | 230 | ||
| @@ -234,39 +247,56 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
| 234 | } | 247 | } |
| 235 | } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && | 248 | } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && |
| 236 | (obj_desc->field.region_obj->region.space_id == | 249 | (obj_desc->field.region_obj->region.space_id == |
| 237 | ACPI_ADR_SPACE_SMBUS)) { | 250 | ACPI_ADR_SPACE_SMBUS |
| 251 | || obj_desc->field.region_obj->region.space_id == | ||
| 252 | ACPI_ADR_SPACE_IPMI)) { | ||
| 238 | /* | 253 | /* |
| 239 | * This is an SMBus write. We will bypass the entire field mechanism | 254 | * This is an SMBus or IPMI write. We will bypass the entire field |
| 240 | * and handoff the buffer directly to the handler. | 255 | * mechanism and handoff the buffer directly to the handler. For |
| 256 | * these address spaces, the buffer is bi-directional; on a write, | ||
| 257 | * return data is returned in the same buffer. | ||
| 258 | * | ||
| 259 | * Source must be a buffer of sufficient size: | ||
| 260 | * ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE. | ||
| 241 | * | 261 | * |
| 242 | * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). | 262 | * Note: SMBus protocol type is passed in upper 16-bits of Function |
| 243 | */ | 263 | */ |
| 244 | if (source_desc->common.type != ACPI_TYPE_BUFFER) { | 264 | if (source_desc->common.type != ACPI_TYPE_BUFFER) { |
| 245 | ACPI_ERROR((AE_INFO, | 265 | ACPI_ERROR((AE_INFO, |
| 246 | "SMBus write requires Buffer, found type %s", | 266 | "SMBus or IPMI write requires Buffer, found type %s", |
| 247 | acpi_ut_get_object_type_name(source_desc))); | 267 | acpi_ut_get_object_type_name(source_desc))); |
| 248 | 268 | ||
| 249 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 269 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
| 250 | } | 270 | } |
| 251 | 271 | ||
| 252 | if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { | 272 | if (obj_desc->field.region_obj->region.space_id == |
| 273 | ACPI_ADR_SPACE_SMBUS) { | ||
| 274 | length = ACPI_SMBUS_BUFFER_SIZE; | ||
| 275 | function = | ||
| 276 | ACPI_WRITE | (obj_desc->field.attribute << 16); | ||
| 277 | } else { /* IPMI */ | ||
| 278 | |||
| 279 | length = ACPI_IPMI_BUFFER_SIZE; | ||
| 280 | function = ACPI_WRITE; | ||
| 281 | } | ||
| 282 | |||
| 283 | if (source_desc->buffer.length < length) { | ||
| 253 | ACPI_ERROR((AE_INFO, | 284 | ACPI_ERROR((AE_INFO, |
| 254 | "SMBus write requires Buffer of length %X, found length %X", | 285 | "SMBus or IPMI write requires Buffer of length %X, found length %X", |
| 255 | ACPI_SMBUS_BUFFER_SIZE, | 286 | length, source_desc->buffer.length)); |
| 256 | source_desc->buffer.length)); | ||
| 257 | 287 | ||
| 258 | return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); | 288 | return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); |
| 259 | } | 289 | } |
| 260 | 290 | ||
| 261 | buffer_desc = | 291 | /* Create the bi-directional buffer */ |
| 262 | acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); | 292 | |
| 293 | buffer_desc = acpi_ut_create_buffer_object(length); | ||
| 263 | if (!buffer_desc) { | 294 | if (!buffer_desc) { |
| 264 | return_ACPI_STATUS(AE_NO_MEMORY); | 295 | return_ACPI_STATUS(AE_NO_MEMORY); |
| 265 | } | 296 | } |
| 266 | 297 | ||
| 267 | buffer = buffer_desc->buffer.pointer; | 298 | buffer = buffer_desc->buffer.pointer; |
| 268 | ACPI_MEMCPY(buffer, source_desc->buffer.pointer, | 299 | ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length); |
| 269 | ACPI_SMBUS_BUFFER_SIZE); | ||
| 270 | 300 | ||
| 271 | /* Lock entire transaction if requested */ | 301 | /* Lock entire transaction if requested */ |
| 272 | 302 | ||
| @@ -275,12 +305,10 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
| 275 | /* | 305 | /* |
| 276 | * Perform the write (returns status and perhaps data in the | 306 | * Perform the write (returns status and perhaps data in the |
| 277 | * same buffer) | 307 | * same buffer) |
| 278 | * Note: SMBus protocol type is passed in upper 16-bits of Function. | ||
| 279 | */ | 308 | */ |
| 280 | status = acpi_ex_access_region(obj_desc, 0, | 309 | status = acpi_ex_access_region(obj_desc, 0, |
| 281 | (acpi_integer *) buffer, | 310 | (acpi_integer *) buffer, |
| 282 | ACPI_WRITE | (obj_desc->field. | 311 | function); |
| 283 | attribute << 16)); | ||
| 284 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); | 312 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
| 285 | 313 | ||
| 286 | *result_desc = buffer_desc; | 314 | *result_desc = buffer_desc; |
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 6687be167f5f..d7b3b418fb45 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c | |||
| @@ -120,12 +120,13 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /* | 122 | /* |
| 123 | * Exit now for SMBus address space, it has a non-linear address space | 123 | * Exit now for SMBus or IPMI address space, it has a non-linear address space |
| 124 | * and the request cannot be directly validated | 124 | * and the request cannot be directly validated |
| 125 | */ | 125 | */ |
| 126 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { | 126 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || |
| 127 | rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { | ||
| 127 | 128 | ||
| 128 | /* SMBus has a non-linear address space */ | 129 | /* SMBus or IPMI has a non-linear address space */ |
| 129 | 130 | ||
| 130 | return_ACPI_STATUS(AE_OK); | 131 | return_ACPI_STATUS(AE_OK); |
| 131 | } | 132 | } |
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 87730e944132..7d41f99f7052 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c | |||
| @@ -358,50 +358,67 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) | |||
| 358 | * | 358 | * |
| 359 | * FUNCTION: acpi_ex_eisa_id_to_string | 359 | * FUNCTION: acpi_ex_eisa_id_to_string |
| 360 | * | 360 | * |
| 361 | * PARAMETERS: numeric_id - EISA ID to be converted | 361 | * PARAMETERS: compressed_id - EISAID to be converted |
| 362 | * out_string - Where to put the converted string (8 bytes) | 362 | * out_string - Where to put the converted string (8 bytes) |
| 363 | * | 363 | * |
| 364 | * RETURN: None | 364 | * RETURN: None |
| 365 | * | 365 | * |
| 366 | * DESCRIPTION: Convert a numeric EISA ID to string representation | 366 | * DESCRIPTION: Convert a numeric EISAID to string representation. Return |
| 367 | * buffer must be large enough to hold the string. The string | ||
| 368 | * returned is always exactly of length ACPI_EISAID_STRING_SIZE | ||
| 369 | * (includes null terminator). The EISAID is always 32 bits. | ||
| 367 | * | 370 | * |
| 368 | ******************************************************************************/ | 371 | ******************************************************************************/ |
| 369 | 372 | ||
| 370 | void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string) | 373 | void acpi_ex_eisa_id_to_string(char *out_string, acpi_integer compressed_id) |
| 371 | { | 374 | { |
| 372 | u32 eisa_id; | 375 | u32 swapped_id; |
| 373 | 376 | ||
| 374 | ACPI_FUNCTION_ENTRY(); | 377 | ACPI_FUNCTION_ENTRY(); |
| 375 | 378 | ||
| 379 | /* The EISAID should be a 32-bit integer */ | ||
| 380 | |||
| 381 | if (compressed_id > ACPI_UINT32_MAX) { | ||
| 382 | ACPI_WARNING((AE_INFO, | ||
| 383 | "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating", | ||
| 384 | ACPI_FORMAT_UINT64(compressed_id))); | ||
| 385 | } | ||
| 386 | |||
| 376 | /* Swap ID to big-endian to get contiguous bits */ | 387 | /* Swap ID to big-endian to get contiguous bits */ |
| 377 | 388 | ||
| 378 | eisa_id = acpi_ut_dword_byte_swap(numeric_id); | 389 | swapped_id = acpi_ut_dword_byte_swap((u32)compressed_id); |
| 379 | 390 | ||
| 380 | out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f)); | 391 | /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */ |
| 381 | out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f)); | 392 | |
| 382 | out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f)); | 393 | out_string[0] = |
| 383 | out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12); | 394 | (char)(0x40 + (((unsigned long)swapped_id >> 26) & 0x1F)); |
| 384 | out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8); | 395 | out_string[1] = (char)(0x40 + ((swapped_id >> 21) & 0x1F)); |
| 385 | out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4); | 396 | out_string[2] = (char)(0x40 + ((swapped_id >> 16) & 0x1F)); |
| 386 | out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0); | 397 | out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 12); |
| 398 | out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 8); | ||
| 399 | out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 4); | ||
| 400 | out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 0); | ||
| 387 | out_string[7] = 0; | 401 | out_string[7] = 0; |
| 388 | } | 402 | } |
| 389 | 403 | ||
| 390 | /******************************************************************************* | 404 | /******************************************************************************* |
| 391 | * | 405 | * |
| 392 | * FUNCTION: acpi_ex_unsigned_integer_to_string | 406 | * FUNCTION: acpi_ex_integer_to_string |
| 393 | * | 407 | * |
| 394 | * PARAMETERS: Value - Value to be converted | 408 | * PARAMETERS: out_string - Where to put the converted string. At least |
| 395 | * out_string - Where to put the converted string (8 bytes) | 409 | * 21 bytes are needed to hold the largest |
| 410 | * possible 64-bit integer. | ||
| 411 | * Value - Value to be converted | ||
| 396 | * | 412 | * |
| 397 | * RETURN: None, string | 413 | * RETURN: None, string |
| 398 | * | 414 | * |
| 399 | * DESCRIPTION: Convert a number to string representation. Assumes string | 415 | * DESCRIPTION: Convert a 64-bit integer to decimal string representation. |
| 400 | * buffer is large enough to hold the string. | 416 | * Assumes string buffer is large enough to hold the string. The |
| 417 | * largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1). | ||
| 401 | * | 418 | * |
| 402 | ******************************************************************************/ | 419 | ******************************************************************************/ |
| 403 | 420 | ||
| 404 | void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string) | 421 | void acpi_ex_integer_to_string(char *out_string, acpi_integer value) |
| 405 | { | 422 | { |
| 406 | u32 count; | 423 | u32 count; |
| 407 | u32 digits_needed; | 424 | u32 digits_needed; |
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index d3b7e37c9eed..c28c41b3180b 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c | |||
| @@ -82,7 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
| 82 | 82 | ||
| 83 | /* Get current value of the enable register that contains this GPE */ | 83 | /* Get current value of the enable register that contains this GPE */ |
| 84 | 84 | ||
| 85 | status = acpi_read(&enable_mask, &gpe_register_info->enable_address); | 85 | status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address); |
| 86 | if (ACPI_FAILURE(status)) { | 86 | if (ACPI_FAILURE(status)) { |
| 87 | return (status); | 87 | return (status); |
| 88 | } | 88 | } |
| @@ -95,7 +95,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
| 95 | 95 | ||
| 96 | /* Write the updated enable mask */ | 96 | /* Write the updated enable mask */ |
| 97 | 97 | ||
| 98 | status = acpi_write(enable_mask, &gpe_register_info->enable_address); | 98 | status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); |
| 99 | return (status); | 99 | return (status); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -130,8 +130,8 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) | |||
| 130 | 130 | ||
| 131 | /* Write the entire GPE (runtime) enable register */ | 131 | /* Write the entire GPE (runtime) enable register */ |
| 132 | 132 | ||
| 133 | status = acpi_write(gpe_register_info->enable_for_run, | 133 | status = acpi_hw_write(gpe_register_info->enable_for_run, |
| 134 | &gpe_register_info->enable_address); | 134 | &gpe_register_info->enable_address); |
| 135 | 135 | ||
| 136 | return (status); | 136 | return (status); |
| 137 | } | 137 | } |
| @@ -163,8 +163,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) | |||
| 163 | * Write a one to the appropriate bit in the status register to | 163 | * Write a one to the appropriate bit in the status register to |
| 164 | * clear this GPE. | 164 | * clear this GPE. |
| 165 | */ | 165 | */ |
| 166 | status = acpi_write(register_bit, | 166 | status = acpi_hw_write(register_bit, |
| 167 | &gpe_event_info->register_info->status_address); | 167 | &gpe_event_info->register_info->status_address); |
| 168 | 168 | ||
| 169 | return (status); | 169 | return (status); |
| 170 | } | 170 | } |
| @@ -222,7 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, | |||
| 222 | 222 | ||
| 223 | /* GPE currently active (status bit == 1)? */ | 223 | /* GPE currently active (status bit == 1)? */ |
| 224 | 224 | ||
| 225 | status = acpi_read(&in_byte, &gpe_register_info->status_address); | 225 | status = acpi_hw_read(&in_byte, &gpe_register_info->status_address); |
| 226 | if (ACPI_FAILURE(status)) { | 226 | if (ACPI_FAILURE(status)) { |
| 227 | goto unlock_and_exit; | 227 | goto unlock_and_exit; |
| 228 | } | 228 | } |
| @@ -266,8 +266,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 266 | /* Disable all GPEs in this register */ | 266 | /* Disable all GPEs in this register */ |
| 267 | 267 | ||
| 268 | status = | 268 | status = |
| 269 | acpi_write(0x00, | 269 | acpi_hw_write(0x00, |
| 270 | &gpe_block->register_info[i].enable_address); | 270 | &gpe_block->register_info[i].enable_address); |
| 271 | if (ACPI_FAILURE(status)) { | 271 | if (ACPI_FAILURE(status)) { |
| 272 | return (status); | 272 | return (status); |
| 273 | } | 273 | } |
| @@ -303,8 +303,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 303 | /* Clear status on all GPEs in this register */ | 303 | /* Clear status on all GPEs in this register */ |
| 304 | 304 | ||
| 305 | status = | 305 | status = |
| 306 | acpi_write(0xFF, | 306 | acpi_hw_write(0xFF, |
| 307 | &gpe_block->register_info[i].status_address); | 307 | &gpe_block->register_info[i].status_address); |
| 308 | if (ACPI_FAILURE(status)) { | 308 | if (ACPI_FAILURE(status)) { |
| 309 | return (status); | 309 | return (status); |
| 310 | } | 310 | } |
| @@ -345,9 +345,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 345 | 345 | ||
| 346 | /* Enable all "runtime" GPEs in this register */ | 346 | /* Enable all "runtime" GPEs in this register */ |
| 347 | 347 | ||
| 348 | status = acpi_write(gpe_block->register_info[i].enable_for_run, | 348 | status = |
| 349 | &gpe_block->register_info[i]. | 349 | acpi_hw_write(gpe_block->register_info[i].enable_for_run, |
| 350 | enable_address); | 350 | &gpe_block->register_info[i].enable_address); |
| 351 | if (ACPI_FAILURE(status)) { | 351 | if (ACPI_FAILURE(status)) { |
| 352 | return (status); | 352 | return (status); |
| 353 | } | 353 | } |
| @@ -387,9 +387,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 387 | 387 | ||
| 388 | /* Enable all "wake" GPEs in this register */ | 388 | /* Enable all "wake" GPEs in this register */ |
| 389 | 389 | ||
| 390 | status = acpi_write(gpe_block->register_info[i].enable_for_wake, | 390 | status = |
| 391 | &gpe_block->register_info[i]. | 391 | acpi_hw_write(gpe_block->register_info[i].enable_for_wake, |
| 392 | enable_address); | 392 | &gpe_block->register_info[i].enable_address); |
| 393 | if (ACPI_FAILURE(status)) { | 393 | if (ACPI_FAILURE(status)) { |
| 394 | return (status); | 394 | return (status); |
| 395 | } | 395 | } |
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 23d5505cb1f7..15c9ed2be853 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
| @@ -62,6 +62,184 @@ acpi_hw_write_multiple(u32 value, | |||
| 62 | struct acpi_generic_address *register_a, | 62 | struct acpi_generic_address *register_a, |
| 63 | struct acpi_generic_address *register_b); | 63 | struct acpi_generic_address *register_b); |
| 64 | 64 | ||
| 65 | /****************************************************************************** | ||
| 66 | * | ||
| 67 | * FUNCTION: acpi_hw_validate_register | ||
| 68 | * | ||
| 69 | * PARAMETERS: Reg - GAS register structure | ||
| 70 | * max_bit_width - Max bit_width supported (32 or 64) | ||
| 71 | * Address - Pointer to where the gas->address | ||
| 72 | * is returned | ||
| 73 | * | ||
| 74 | * RETURN: Status | ||
| 75 | * | ||
| 76 | * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS | ||
| 77 | * pointer, Address, space_id, bit_width, and bit_offset. | ||
| 78 | * | ||
| 79 | ******************************************************************************/ | ||
| 80 | |||
| 81 | acpi_status | ||
| 82 | acpi_hw_validate_register(struct acpi_generic_address *reg, | ||
| 83 | u8 max_bit_width, u64 *address) | ||
| 84 | { | ||
| 85 | |||
| 86 | /* Must have a valid pointer to a GAS structure */ | ||
| 87 | |||
| 88 | if (!reg) { | ||
| 89 | return (AE_BAD_PARAMETER); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Copy the target address. This handles possible alignment issues. | ||
| 94 | * Address must not be null. A null address also indicates an optional | ||
| 95 | * ACPI register that is not supported, so no error message. | ||
| 96 | */ | ||
| 97 | ACPI_MOVE_64_TO_64(address, ®->address); | ||
| 98 | if (!(*address)) { | ||
| 99 | return (AE_BAD_ADDRESS); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* Validate the space_iD */ | ||
| 103 | |||
| 104 | if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && | ||
| 105 | (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { | ||
| 106 | ACPI_ERROR((AE_INFO, | ||
| 107 | "Unsupported address space: 0x%X", reg->space_id)); | ||
| 108 | return (AE_SUPPORT); | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Validate the bit_width */ | ||
| 112 | |||
| 113 | if ((reg->bit_width != 8) && | ||
| 114 | (reg->bit_width != 16) && | ||
| 115 | (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) { | ||
| 116 | ACPI_ERROR((AE_INFO, | ||
| 117 | "Unsupported register bit width: 0x%X", | ||
| 118 | reg->bit_width)); | ||
| 119 | return (AE_SUPPORT); | ||
| 120 | } | ||
| 121 | |||
| 122 | /* Validate the bit_offset. Just a warning for now. */ | ||
| 123 | |||
| 124 | if (reg->bit_offset != 0) { | ||
| 125 | ACPI_WARNING((AE_INFO, | ||
| 126 | "Unsupported register bit offset: 0x%X", | ||
| 127 | reg->bit_offset)); | ||
| 128 | } | ||
| 129 | |||
| 130 | return (AE_OK); | ||
| 131 | } | ||
| 132 | |||
| 133 | /****************************************************************************** | ||
| 134 | * | ||
| 135 | * FUNCTION: acpi_hw_read | ||
| 136 | * | ||
| 137 | * PARAMETERS: Value - Where the value is returned | ||
| 138 | * Reg - GAS register structure | ||
| 139 | * | ||
| 140 | * RETURN: Status | ||
| 141 | * | ||
| 142 | * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max | ||
| 143 | * version of acpi_read, used internally since the overhead of | ||
| 144 | * 64-bit values is not needed. | ||
| 145 | * | ||
| 146 | * LIMITATIONS: <These limitations also apply to acpi_hw_write> | ||
| 147 | * bit_width must be exactly 8, 16, or 32. | ||
| 148 | * space_iD must be system_memory or system_iO. | ||
| 149 | * bit_offset and access_width are currently ignored, as there has | ||
| 150 | * not been a need to implement these. | ||
| 151 | * | ||
| 152 | ******************************************************************************/ | ||
| 153 | |||
| 154 | acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) | ||
| 155 | { | ||
| 156 | u64 address; | ||
| 157 | acpi_status status; | ||
| 158 | |||
| 159 | ACPI_FUNCTION_NAME(hw_read); | ||
| 160 | |||
| 161 | /* Validate contents of the GAS register */ | ||
| 162 | |||
| 163 | status = acpi_hw_validate_register(reg, 32, &address); | ||
| 164 | if (ACPI_FAILURE(status)) { | ||
| 165 | return (status); | ||
| 166 | } | ||
| 167 | |||
| 168 | /* Initialize entire 32-bit return value to zero */ | ||
| 169 | |||
| 170 | *value = 0; | ||
| 171 | |||
| 172 | /* | ||
| 173 | * Two address spaces supported: Memory or IO. PCI_Config is | ||
| 174 | * not supported here because the GAS structure is insufficient | ||
| 175 | */ | ||
| 176 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
| 177 | status = acpi_os_read_memory((acpi_physical_address) | ||
| 178 | address, value, reg->bit_width); | ||
| 179 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 180 | |||
| 181 | status = acpi_hw_read_port((acpi_io_address) | ||
| 182 | address, value, reg->bit_width); | ||
| 183 | } | ||
| 184 | |||
| 185 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | ||
| 186 | "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", | ||
| 187 | *value, reg->bit_width, ACPI_FORMAT_UINT64(address), | ||
| 188 | acpi_ut_get_region_name(reg->space_id))); | ||
| 189 | |||
| 190 | return (status); | ||
| 191 | } | ||
| 192 | |||
| 193 | /****************************************************************************** | ||
| 194 | * | ||
| 195 | * FUNCTION: acpi_hw_write | ||
| 196 | * | ||
| 197 | * PARAMETERS: Value - Value to be written | ||
| 198 | * Reg - GAS register structure | ||
| 199 | * | ||
| 200 | * RETURN: Status | ||
| 201 | * | ||
| 202 | * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max | ||
| 203 | * version of acpi_write, used internally since the overhead of | ||
| 204 | * 64-bit values is not needed. | ||
| 205 | * | ||
| 206 | ******************************************************************************/ | ||
| 207 | |||
| 208 | acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) | ||
| 209 | { | ||
| 210 | u64 address; | ||
| 211 | acpi_status status; | ||
| 212 | |||
| 213 | ACPI_FUNCTION_NAME(hw_write); | ||
| 214 | |||
| 215 | /* Validate contents of the GAS register */ | ||
| 216 | |||
| 217 | status = acpi_hw_validate_register(reg, 32, &address); | ||
| 218 | if (ACPI_FAILURE(status)) { | ||
| 219 | return (status); | ||
| 220 | } | ||
| 221 | |||
| 222 | /* | ||
| 223 | * Two address spaces supported: Memory or IO. PCI_Config is | ||
| 224 | * not supported here because the GAS structure is insufficient | ||
| 225 | */ | ||
| 226 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { | ||
| 227 | status = acpi_os_write_memory((acpi_physical_address) | ||
| 228 | address, value, reg->bit_width); | ||
| 229 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 230 | |||
| 231 | status = acpi_hw_write_port((acpi_io_address) | ||
| 232 | address, value, reg->bit_width); | ||
| 233 | } | ||
| 234 | |||
| 235 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | ||
| 236 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", | ||
| 237 | value, reg->bit_width, ACPI_FORMAT_UINT64(address), | ||
| 238 | acpi_ut_get_region_name(reg->space_id))); | ||
| 239 | |||
| 240 | return (status); | ||
| 241 | } | ||
| 242 | |||
| 65 | /******************************************************************************* | 243 | /******************************************************************************* |
| 66 | * | 244 | * |
| 67 | * FUNCTION: acpi_hw_clear_acpi_status | 245 | * FUNCTION: acpi_hw_clear_acpi_status |
| @@ -152,15 +330,16 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) | |||
| 152 | 330 | ||
| 153 | ACPI_FUNCTION_TRACE(hw_write_pm1_control); | 331 | ACPI_FUNCTION_TRACE(hw_write_pm1_control); |
| 154 | 332 | ||
| 155 | status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); | 333 | status = |
| 334 | acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); | ||
| 156 | if (ACPI_FAILURE(status)) { | 335 | if (ACPI_FAILURE(status)) { |
| 157 | return_ACPI_STATUS(status); | 336 | return_ACPI_STATUS(status); |
| 158 | } | 337 | } |
| 159 | 338 | ||
| 160 | if (acpi_gbl_FADT.xpm1b_control_block.address) { | 339 | if (acpi_gbl_FADT.xpm1b_control_block.address) { |
| 161 | status = | 340 | status = |
| 162 | acpi_write(pm1b_control, | 341 | acpi_hw_write(pm1b_control, |
| 163 | &acpi_gbl_FADT.xpm1b_control_block); | 342 | &acpi_gbl_FADT.xpm1b_control_block); |
| 164 | } | 343 | } |
| 165 | return_ACPI_STATUS(status); | 344 | return_ACPI_STATUS(status); |
| 166 | } | 345 | } |
| @@ -218,12 +397,13 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) | |||
| 218 | 397 | ||
| 219 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ | 398 | case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ |
| 220 | 399 | ||
| 221 | status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block); | 400 | status = |
| 401 | acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block); | ||
| 222 | break; | 402 | break; |
| 223 | 403 | ||
| 224 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ | 404 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ |
| 225 | 405 | ||
| 226 | status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block); | 406 | status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block); |
| 227 | break; | 407 | break; |
| 228 | 408 | ||
| 229 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ | 409 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ |
| @@ -340,7 +520,8 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
| 340 | * as per the ACPI spec. | 520 | * as per the ACPI spec. |
| 341 | */ | 521 | */ |
| 342 | status = | 522 | status = |
| 343 | acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block); | 523 | acpi_hw_read(&read_value, |
| 524 | &acpi_gbl_FADT.xpm2_control_block); | ||
| 344 | if (ACPI_FAILURE(status)) { | 525 | if (ACPI_FAILURE(status)) { |
| 345 | goto exit; | 526 | goto exit; |
| 346 | } | 527 | } |
| @@ -350,12 +531,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
| 350 | ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, | 531 | ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, |
| 351 | read_value); | 532 | read_value); |
| 352 | 533 | ||
| 353 | status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); | 534 | status = |
| 535 | acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block); | ||
| 354 | break; | 536 | break; |
| 355 | 537 | ||
| 356 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ | 538 | case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ |
| 357 | 539 | ||
| 358 | status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block); | 540 | status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block); |
| 359 | break; | 541 | break; |
| 360 | 542 | ||
| 361 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ | 543 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ |
| @@ -401,7 +583,7 @@ acpi_hw_read_multiple(u32 *value, | |||
| 401 | 583 | ||
| 402 | /* The first register is always required */ | 584 | /* The first register is always required */ |
| 403 | 585 | ||
| 404 | status = acpi_read(&value_a, register_a); | 586 | status = acpi_hw_read(&value_a, register_a); |
| 405 | if (ACPI_FAILURE(status)) { | 587 | if (ACPI_FAILURE(status)) { |
| 406 | return (status); | 588 | return (status); |
| 407 | } | 589 | } |
| @@ -409,7 +591,7 @@ acpi_hw_read_multiple(u32 *value, | |||
| 409 | /* Second register is optional */ | 591 | /* Second register is optional */ |
| 410 | 592 | ||
| 411 | if (register_b->address) { | 593 | if (register_b->address) { |
| 412 | status = acpi_read(&value_b, register_b); | 594 | status = acpi_hw_read(&value_b, register_b); |
| 413 | if (ACPI_FAILURE(status)) { | 595 | if (ACPI_FAILURE(status)) { |
| 414 | return (status); | 596 | return (status); |
| 415 | } | 597 | } |
| @@ -452,7 +634,7 @@ acpi_hw_write_multiple(u32 value, | |||
| 452 | 634 | ||
| 453 | /* The first register is always required */ | 635 | /* The first register is always required */ |
| 454 | 636 | ||
| 455 | status = acpi_write(value, register_a); | 637 | status = acpi_hw_write(value, register_a); |
| 456 | if (ACPI_FAILURE(status)) { | 638 | if (ACPI_FAILURE(status)) { |
| 457 | return (status); | 639 | return (status); |
| 458 | } | 640 | } |
| @@ -470,7 +652,7 @@ acpi_hw_write_multiple(u32 value, | |||
| 470 | * and writes have no side effects" | 652 | * and writes have no side effects" |
| 471 | */ | 653 | */ |
| 472 | if (register_b->address) { | 654 | if (register_b->address) { |
| 473 | status = acpi_write(value, register_b); | 655 | status = acpi_hw_write(value, register_b); |
| 474 | } | 656 | } |
| 475 | 657 | ||
| 476 | return (status); | 658 | return (status); |
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index b7f522c8f023..6b282e85d039 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c | |||
| @@ -100,7 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks) | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | status = | 102 | status = |
| 103 | acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block); | 103 | acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); |
| 104 | 104 | ||
| 105 | return_ACPI_STATUS(status); | 105 | return_ACPI_STATUS(status); |
| 106 | } | 106 | } |
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 9829979f2bdd..647c7b6e6756 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c | |||
| @@ -78,9 +78,22 @@ acpi_status acpi_reset(void) | |||
| 78 | return_ACPI_STATUS(AE_NOT_EXIST); | 78 | return_ACPI_STATUS(AE_NOT_EXIST); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | /* Write the reset value to the reset register */ | 81 | if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { |
| 82 | /* | ||
| 83 | * For I/O space, write directly to the OSL. This bypasses the port | ||
| 84 | * validation mechanism, which may block a valid write to the reset | ||
| 85 | * register. | ||
| 86 | */ | ||
| 87 | status = | ||
| 88 | acpi_os_write_port((acpi_io_address) reset_reg->address, | ||
| 89 | acpi_gbl_FADT.reset_value, | ||
| 90 | reset_reg->bit_width); | ||
| 91 | } else { | ||
| 92 | /* Write the reset value to the reset register */ | ||
| 93 | |||
| 94 | status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg); | ||
| 95 | } | ||
| 82 | 96 | ||
| 83 | status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); | ||
| 84 | return_ACPI_STATUS(status); | 97 | return_ACPI_STATUS(status); |
| 85 | } | 98 | } |
| 86 | 99 | ||
| @@ -97,67 +110,92 @@ ACPI_EXPORT_SYMBOL(acpi_reset) | |||
| 97 | * | 110 | * |
| 98 | * DESCRIPTION: Read from either memory or IO space. | 111 | * DESCRIPTION: Read from either memory or IO space. |
| 99 | * | 112 | * |
| 113 | * LIMITATIONS: <These limitations also apply to acpi_write> | ||
| 114 | * bit_width must be exactly 8, 16, 32, or 64. | ||
| 115 | * space_iD must be system_memory or system_iO. | ||
| 116 | * bit_offset and access_width are currently ignored, as there has | ||
| 117 | * not been a need to implement these. | ||
| 118 | * | ||
| 100 | ******************************************************************************/ | 119 | ******************************************************************************/ |
| 101 | acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) | 120 | acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) |
| 102 | { | 121 | { |
| 122 | u32 value; | ||
| 103 | u32 width; | 123 | u32 width; |
| 104 | u64 address; | 124 | u64 address; |
| 105 | acpi_status status; | 125 | acpi_status status; |
| 106 | 126 | ||
| 107 | ACPI_FUNCTION_NAME(acpi_read); | 127 | ACPI_FUNCTION_NAME(acpi_read); |
| 108 | 128 | ||
| 109 | /* | 129 | if (!return_value) { |
| 110 | * Must have a valid pointer to a GAS structure, and a non-zero address | ||
| 111 | * within. | ||
| 112 | */ | ||
| 113 | if (!reg) { | ||
| 114 | return (AE_BAD_PARAMETER); | 130 | return (AE_BAD_PARAMETER); |
| 115 | } | 131 | } |
| 116 | 132 | ||
| 117 | /* Get a local copy of the address. Handles possible alignment issues */ | 133 | /* Validate contents of the GAS register. Allow 64-bit transfers */ |
| 118 | 134 | ||
| 119 | ACPI_MOVE_64_TO_64(&address, ®->address); | 135 | status = acpi_hw_validate_register(reg, 64, &address); |
| 120 | if (!address) { | 136 | if (ACPI_FAILURE(status)) { |
| 121 | return (AE_BAD_ADDRESS); | 137 | return (status); |
| 122 | } | 138 | } |
| 123 | 139 | ||
| 124 | /* Supported widths are 8/16/32 */ | ||
| 125 | |||
| 126 | width = reg->bit_width; | 140 | width = reg->bit_width; |
| 127 | if ((width != 8) && (width != 16) && (width != 32)) { | 141 | if (width == 64) { |
| 128 | return (AE_SUPPORT); | 142 | width = 32; /* Break into two 32-bit transfers */ |
| 129 | } | 143 | } |
| 130 | 144 | ||
| 131 | /* Initialize entire 32-bit return value to zero */ | 145 | /* Initialize entire 64-bit return value to zero */ |
| 132 | 146 | ||
| 133 | *value = 0; | 147 | *return_value = 0; |
| 148 | value = 0; | ||
| 134 | 149 | ||
| 135 | /* | 150 | /* |
| 136 | * Two address spaces supported: Memory or IO. PCI_Config is | 151 | * Two address spaces supported: Memory or IO. PCI_Config is |
| 137 | * not supported here because the GAS structure is insufficient | 152 | * not supported here because the GAS structure is insufficient |
| 138 | */ | 153 | */ |
| 139 | switch (reg->space_id) { | 154 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
| 140 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 155 | status = acpi_os_read_memory((acpi_physical_address) |
| 156 | address, &value, width); | ||
| 157 | if (ACPI_FAILURE(status)) { | ||
| 158 | return (status); | ||
| 159 | } | ||
| 160 | *return_value = value; | ||
| 141 | 161 | ||
| 142 | status = acpi_os_read_memory((acpi_physical_address) address, | 162 | if (reg->bit_width == 64) { |
| 143 | value, width); | ||
| 144 | break; | ||
| 145 | 163 | ||
| 146 | case ACPI_ADR_SPACE_SYSTEM_IO: | 164 | /* Read the top 32 bits */ |
| 147 | 165 | ||
| 148 | status = | 166 | status = acpi_os_read_memory((acpi_physical_address) |
| 149 | acpi_hw_read_port((acpi_io_address) address, value, width); | 167 | (address + 4), &value, 32); |
| 150 | break; | 168 | if (ACPI_FAILURE(status)) { |
| 169 | return (status); | ||
| 170 | } | ||
| 171 | *return_value |= ((u64)value << 32); | ||
| 172 | } | ||
| 173 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 151 | 174 | ||
| 152 | default: | 175 | status = acpi_hw_read_port((acpi_io_address) |
| 153 | ACPI_ERROR((AE_INFO, | 176 | address, &value, width); |
| 154 | "Unsupported address space: %X", reg->space_id)); | 177 | if (ACPI_FAILURE(status)) { |
| 155 | return (AE_BAD_PARAMETER); | 178 | return (status); |
| 179 | } | ||
| 180 | *return_value = value; | ||
| 181 | |||
| 182 | if (reg->bit_width == 64) { | ||
| 183 | |||
| 184 | /* Read the top 32 bits */ | ||
| 185 | |||
| 186 | status = acpi_hw_read_port((acpi_io_address) | ||
| 187 | (address + 4), &value, 32); | ||
| 188 | if (ACPI_FAILURE(status)) { | ||
| 189 | return (status); | ||
| 190 | } | ||
| 191 | *return_value |= ((u64)value << 32); | ||
| 192 | } | ||
| 156 | } | 193 | } |
| 157 | 194 | ||
| 158 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 195 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
| 159 | "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", | 196 | "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", |
| 160 | *value, width, ACPI_FORMAT_UINT64(address), | 197 | ACPI_FORMAT_UINT64(*return_value), reg->bit_width, |
| 198 | ACPI_FORMAT_UINT64(address), | ||
| 161 | acpi_ut_get_region_name(reg->space_id))); | 199 | acpi_ut_get_region_name(reg->space_id))); |
| 162 | 200 | ||
| 163 | return (status); | 201 | return (status); |
| @@ -169,7 +207,7 @@ ACPI_EXPORT_SYMBOL(acpi_read) | |||
| 169 | * | 207 | * |
| 170 | * FUNCTION: acpi_write | 208 | * FUNCTION: acpi_write |
| 171 | * | 209 | * |
| 172 | * PARAMETERS: Value - To be written | 210 | * PARAMETERS: Value - Value to be written |
| 173 | * Reg - GAS register structure | 211 | * Reg - GAS register structure |
| 174 | * | 212 | * |
| 175 | * RETURN: Status | 213 | * RETURN: Status |
| @@ -177,7 +215,7 @@ ACPI_EXPORT_SYMBOL(acpi_read) | |||
| 177 | * DESCRIPTION: Write to either memory or IO space. | 215 | * DESCRIPTION: Write to either memory or IO space. |
| 178 | * | 216 | * |
| 179 | ******************************************************************************/ | 217 | ******************************************************************************/ |
| 180 | acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) | 218 | acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) |
| 181 | { | 219 | { |
| 182 | u32 width; | 220 | u32 width; |
| 183 | u64 address; | 221 | u64 address; |
| @@ -185,54 +223,61 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) | |||
| 185 | 223 | ||
| 186 | ACPI_FUNCTION_NAME(acpi_write); | 224 | ACPI_FUNCTION_NAME(acpi_write); |
| 187 | 225 | ||
| 188 | /* | 226 | /* Validate contents of the GAS register. Allow 64-bit transfers */ |
| 189 | * Must have a valid pointer to a GAS structure, and a non-zero address | ||
| 190 | * within. | ||
| 191 | */ | ||
| 192 | if (!reg) { | ||
| 193 | return (AE_BAD_PARAMETER); | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Get a local copy of the address. Handles possible alignment issues */ | ||
| 197 | 227 | ||
| 198 | ACPI_MOVE_64_TO_64(&address, ®->address); | 228 | status = acpi_hw_validate_register(reg, 64, &address); |
| 199 | if (!address) { | 229 | if (ACPI_FAILURE(status)) { |
| 200 | return (AE_BAD_ADDRESS); | 230 | return (status); |
| 201 | } | 231 | } |
| 202 | 232 | ||
| 203 | /* Supported widths are 8/16/32 */ | ||
| 204 | |||
| 205 | width = reg->bit_width; | 233 | width = reg->bit_width; |
| 206 | if ((width != 8) && (width != 16) && (width != 32)) { | 234 | if (width == 64) { |
| 207 | return (AE_SUPPORT); | 235 | width = 32; /* Break into two 32-bit transfers */ |
| 208 | } | 236 | } |
| 209 | 237 | ||
| 210 | /* | 238 | /* |
| 211 | * Two address spaces supported: Memory or IO. | 239 | * Two address spaces supported: Memory or IO. PCI_Config is |
| 212 | * PCI_Config is not supported here because the GAS struct is insufficient | 240 | * not supported here because the GAS structure is insufficient |
| 213 | */ | 241 | */ |
| 214 | switch (reg->space_id) { | 242 | if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
| 215 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | 243 | status = acpi_os_write_memory((acpi_physical_address) |
| 216 | 244 | address, ACPI_LODWORD(value), | |
| 217 | status = acpi_os_write_memory((acpi_physical_address) address, | 245 | width); |
| 218 | value, width); | 246 | if (ACPI_FAILURE(status)) { |
| 219 | break; | 247 | return (status); |
| 248 | } | ||
| 220 | 249 | ||
| 221 | case ACPI_ADR_SPACE_SYSTEM_IO: | 250 | if (reg->bit_width == 64) { |
| 251 | status = acpi_os_write_memory((acpi_physical_address) | ||
| 252 | (address + 4), | ||
| 253 | ACPI_HIDWORD(value), 32); | ||
| 254 | if (ACPI_FAILURE(status)) { | ||
| 255 | return (status); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ | ||
| 222 | 259 | ||
| 223 | status = acpi_hw_write_port((acpi_io_address) address, value, | 260 | status = acpi_hw_write_port((acpi_io_address) |
| 261 | address, ACPI_LODWORD(value), | ||
| 224 | width); | 262 | width); |
| 225 | break; | 263 | if (ACPI_FAILURE(status)) { |
| 264 | return (status); | ||
| 265 | } | ||
| 226 | 266 | ||
| 227 | default: | 267 | if (reg->bit_width == 64) { |
| 228 | ACPI_ERROR((AE_INFO, | 268 | status = acpi_hw_write_port((acpi_io_address) |
| 229 | "Unsupported address space: %X", reg->space_id)); | 269 | (address + 4), |
| 230 | return (AE_BAD_PARAMETER); | 270 | ACPI_HIDWORD(value), 32); |
| 271 | if (ACPI_FAILURE(status)) { | ||
| 272 | return (status); | ||
| 273 | } | ||
| 274 | } | ||
| 231 | } | 275 | } |
| 232 | 276 | ||
| 233 | ACPI_DEBUG_PRINT((ACPI_DB_IO, | 277 | ACPI_DEBUG_PRINT((ACPI_DB_IO, |
| 234 | "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", | 278 | "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", |
| 235 | value, width, ACPI_FORMAT_UINT64(address), | 279 | ACPI_FORMAT_UINT64(value), reg->bit_width, |
| 280 | ACPI_FORMAT_UINT64(address), | ||
| 236 | acpi_ut_get_region_name(reg->space_id))); | 281 | acpi_ut_get_region_name(reg->space_id))); |
| 237 | 282 | ||
| 238 | return (status); | 283 | return (status); |
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index efc971ab7d65..8a58a1b85aa0 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c | |||
| @@ -96,17 +96,68 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) | |||
| 96 | * | 96 | * |
| 97 | * RETURN: None | 97 | * RETURN: None |
| 98 | * | 98 | * |
| 99 | * DESCRIPTION: Delete a namespace node | 99 | * DESCRIPTION: Delete a namespace node. All node deletions must come through |
| 100 | * here. Detaches any attached objects, including any attached | ||
| 101 | * data. If a handler is associated with attached data, it is | ||
| 102 | * invoked before the node is deleted. | ||
| 100 | * | 103 | * |
| 101 | ******************************************************************************/ | 104 | ******************************************************************************/ |
| 102 | 105 | ||
| 103 | void acpi_ns_delete_node(struct acpi_namespace_node *node) | 106 | void acpi_ns_delete_node(struct acpi_namespace_node *node) |
| 104 | { | 107 | { |
| 108 | union acpi_operand_object *obj_desc; | ||
| 109 | |||
| 110 | ACPI_FUNCTION_NAME(ns_delete_node); | ||
| 111 | |||
| 112 | /* Detach an object if there is one */ | ||
| 113 | |||
| 114 | acpi_ns_detach_object(node); | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Delete an attached data object if present (an object that was created | ||
| 118 | * and attached via acpi_attach_data). Note: After any normal object is | ||
| 119 | * detached above, the only possible remaining object is a data object. | ||
| 120 | */ | ||
| 121 | obj_desc = node->object; | ||
| 122 | if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { | ||
| 123 | |||
| 124 | /* Invoke the attached data deletion handler if present */ | ||
| 125 | |||
| 126 | if (obj_desc->data.handler) { | ||
| 127 | obj_desc->data.handler(node, obj_desc->data.pointer); | ||
| 128 | } | ||
| 129 | |||
| 130 | acpi_ut_remove_reference(obj_desc); | ||
| 131 | } | ||
| 132 | |||
| 133 | /* Now we can delete the node */ | ||
| 134 | |||
| 135 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); | ||
| 136 | |||
| 137 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | ||
| 138 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", | ||
| 139 | node, acpi_gbl_current_node_count)); | ||
| 140 | } | ||
| 141 | |||
| 142 | /******************************************************************************* | ||
| 143 | * | ||
| 144 | * FUNCTION: acpi_ns_remove_node | ||
| 145 | * | ||
| 146 | * PARAMETERS: Node - Node to be removed/deleted | ||
| 147 | * | ||
| 148 | * RETURN: None | ||
| 149 | * | ||
| 150 | * DESCRIPTION: Remove (unlink) and delete a namespace node | ||
| 151 | * | ||
| 152 | ******************************************************************************/ | ||
| 153 | |||
| 154 | void acpi_ns_remove_node(struct acpi_namespace_node *node) | ||
| 155 | { | ||
| 105 | struct acpi_namespace_node *parent_node; | 156 | struct acpi_namespace_node *parent_node; |
| 106 | struct acpi_namespace_node *prev_node; | 157 | struct acpi_namespace_node *prev_node; |
| 107 | struct acpi_namespace_node *next_node; | 158 | struct acpi_namespace_node *next_node; |
| 108 | 159 | ||
| 109 | ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); | 160 | ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); |
| 110 | 161 | ||
| 111 | parent_node = acpi_ns_get_parent_node(node); | 162 | parent_node = acpi_ns_get_parent_node(node); |
| 112 | 163 | ||
| @@ -142,12 +193,9 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) | |||
| 142 | } | 193 | } |
| 143 | } | 194 | } |
| 144 | 195 | ||
| 145 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | 196 | /* Delete the node and any attached objects */ |
| 146 | |||
| 147 | /* Detach an object if there is one, then delete the node */ | ||
| 148 | 197 | ||
| 149 | acpi_ns_detach_object(node); | 198 | acpi_ns_delete_node(node); |
| 150 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); | ||
| 151 | return_VOID; | 199 | return_VOID; |
| 152 | } | 200 | } |
| 153 | 201 | ||
| @@ -273,25 +321,11 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
| 273 | parent_node, child_node)); | 321 | parent_node, child_node)); |
| 274 | } | 322 | } |
| 275 | 323 | ||
| 276 | /* Now we can free this child object */ | 324 | /* |
| 277 | 325 | * Delete this child node and move on to the next child in the list. | |
| 278 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | 326 | * No need to unlink the node since we are deleting the entire branch. |
| 279 | 327 | */ | |
| 280 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, | 328 | acpi_ns_delete_node(child_node); |
| 281 | "Object %p, Remaining %X\n", child_node, | ||
| 282 | acpi_gbl_current_node_count)); | ||
| 283 | |||
| 284 | /* Detach an object if there is one, then free the child node */ | ||
| 285 | |||
| 286 | acpi_ns_detach_object(child_node); | ||
| 287 | |||
| 288 | /* Now we can delete the node */ | ||
| 289 | |||
| 290 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, | ||
| 291 | child_node); | ||
| 292 | |||
| 293 | /* And move on to the next child in the list */ | ||
| 294 | |||
| 295 | child_node = next_node; | 329 | child_node = next_node; |
| 296 | 330 | ||
| 297 | } while (!(flags & ANOBJ_END_OF_PEER_LIST)); | 331 | } while (!(flags & ANOBJ_END_OF_PEER_LIST)); |
| @@ -433,7 +467,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) | |||
| 433 | 467 | ||
| 434 | if (deletion_node) { | 468 | if (deletion_node) { |
| 435 | acpi_ns_delete_children(deletion_node); | 469 | acpi_ns_delete_children(deletion_node); |
| 436 | acpi_ns_delete_node(deletion_node); | 470 | acpi_ns_remove_node(deletion_node); |
| 437 | deletion_node = NULL; | 471 | deletion_node = NULL; |
| 438 | } | 472 | } |
| 439 | 473 | ||
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 41994fe7fbb8..0fe87f1aef16 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c | |||
| @@ -70,7 +70,6 @@ static acpi_status | |||
| 70 | acpi_ns_dump_one_device(acpi_handle obj_handle, | 70 | acpi_ns_dump_one_device(acpi_handle obj_handle, |
| 71 | u32 level, void *context, void **return_value) | 71 | u32 level, void *context, void **return_value) |
| 72 | { | 72 | { |
| 73 | struct acpi_buffer buffer; | ||
| 74 | struct acpi_device_info *info; | 73 | struct acpi_device_info *info; |
| 75 | acpi_status status; | 74 | acpi_status status; |
| 76 | u32 i; | 75 | u32 i; |
| @@ -80,17 +79,15 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, | |||
| 80 | status = | 79 | status = |
| 81 | acpi_ns_dump_one_object(obj_handle, level, context, return_value); | 80 | acpi_ns_dump_one_object(obj_handle, level, context, return_value); |
| 82 | 81 | ||
| 83 | buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | 82 | status = acpi_get_object_info(obj_handle, &info); |
| 84 | status = acpi_get_object_info(obj_handle, &buffer); | ||
| 85 | if (ACPI_SUCCESS(status)) { | 83 | if (ACPI_SUCCESS(status)) { |
| 86 | info = buffer.pointer; | ||
| 87 | for (i = 0; i < level; i++) { | 84 | for (i = 0; i < level; i++) { |
| 88 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); | 85 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); |
| 89 | } | 86 | } |
| 90 | 87 | ||
| 91 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, | 88 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, |
| 92 | " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", | 89 | " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", |
| 93 | info->hardware_id.value, | 90 | info->hardware_id.string, |
| 94 | ACPI_FORMAT_UINT64(info->address), | 91 | ACPI_FORMAT_UINT64(info->address), |
| 95 | info->current_status)); | 92 | info->current_status)); |
| 96 | ACPI_FREE(info); | 93 | ACPI_FREE(info); |
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 8e7dec1176c9..846d1132feb1 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c | |||
| @@ -50,6 +50,11 @@ | |||
| 50 | #define _COMPONENT ACPI_NAMESPACE | 50 | #define _COMPONENT ACPI_NAMESPACE |
| 51 | ACPI_MODULE_NAME("nseval") | 51 | ACPI_MODULE_NAME("nseval") |
| 52 | 52 | ||
| 53 | /* Local prototypes */ | ||
| 54 | static void | ||
| 55 | acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | ||
| 56 | struct acpi_evaluate_info *info); | ||
| 57 | |||
| 53 | /******************************************************************************* | 58 | /******************************************************************************* |
| 54 | * | 59 | * |
| 55 | * FUNCTION: acpi_ns_evaluate | 60 | * FUNCTION: acpi_ns_evaluate |
| @@ -76,6 +81,7 @@ ACPI_MODULE_NAME("nseval") | |||
| 76 | * MUTEX: Locks interpreter | 81 | * MUTEX: Locks interpreter |
| 77 | * | 82 | * |
| 78 | ******************************************************************************/ | 83 | ******************************************************************************/ |
| 84 | |||
| 79 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | 85 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) |
| 80 | { | 86 | { |
| 81 | acpi_status status; | 87 | acpi_status status; |
| @@ -276,3 +282,134 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | |||
| 276 | */ | 282 | */ |
| 277 | return_ACPI_STATUS(status); | 283 | return_ACPI_STATUS(status); |
| 278 | } | 284 | } |
| 285 | |||
| 286 | /******************************************************************************* | ||
| 287 | * | ||
| 288 | * FUNCTION: acpi_ns_exec_module_code_list | ||
| 289 | * | ||
| 290 | * PARAMETERS: None | ||
| 291 | * | ||
| 292 | * RETURN: None. Exceptions during method execution are ignored, since | ||
| 293 | * we cannot abort a table load. | ||
| 294 | * | ||
| 295 | * DESCRIPTION: Execute all elements of the global module-level code list. | ||
| 296 | * Each element is executed as a single control method. | ||
| 297 | * | ||
| 298 | ******************************************************************************/ | ||
| 299 | |||
| 300 | void acpi_ns_exec_module_code_list(void) | ||
| 301 | { | ||
| 302 | union acpi_operand_object *prev; | ||
| 303 | union acpi_operand_object *next; | ||
| 304 | struct acpi_evaluate_info *info; | ||
| 305 | u32 method_count = 0; | ||
| 306 | |||
| 307 | ACPI_FUNCTION_TRACE(ns_exec_module_code_list); | ||
| 308 | |||
| 309 | /* Exit now if the list is empty */ | ||
| 310 | |||
| 311 | next = acpi_gbl_module_code_list; | ||
| 312 | if (!next) { | ||
| 313 | return_VOID; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* Allocate the evaluation information block */ | ||
| 317 | |||
| 318 | info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info)); | ||
| 319 | if (!info) { | ||
| 320 | return_VOID; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* Walk the list, executing each "method" */ | ||
| 324 | |||
| 325 | while (next) { | ||
| 326 | prev = next; | ||
| 327 | next = next->method.mutex; | ||
| 328 | |||
| 329 | /* Clear the link field and execute the method */ | ||
| 330 | |||
| 331 | prev->method.mutex = NULL; | ||
| 332 | acpi_ns_exec_module_code(prev, info); | ||
| 333 | method_count++; | ||
| 334 | |||
| 335 | /* Delete the (temporary) method object */ | ||
| 336 | |||
| 337 | acpi_ut_remove_reference(prev); | ||
| 338 | } | ||
| 339 | |||
| 340 | ACPI_INFO((AE_INFO, | ||
| 341 | "Executed %u blocks of module-level executable AML code", | ||
| 342 | method_count)); | ||
| 343 | |||
| 344 | ACPI_FREE(info); | ||
| 345 | acpi_gbl_module_code_list = NULL; | ||
| 346 | return_VOID; | ||
| 347 | } | ||
| 348 | |||
| 349 | /******************************************************************************* | ||
| 350 | * | ||
| 351 | * FUNCTION: acpi_ns_exec_module_code | ||
| 352 | * | ||
| 353 | * PARAMETERS: method_obj - Object container for the module-level code | ||
| 354 | * Info - Info block for method evaluation | ||
| 355 | * | ||
| 356 | * RETURN: None. Exceptions during method execution are ignored, since | ||
| 357 | * we cannot abort a table load. | ||
| 358 | * | ||
| 359 | * DESCRIPTION: Execute a control method containing a block of module-level | ||
| 360 | * executable AML code. The control method is temporarily | ||
| 361 | * installed to the root node, then evaluated. | ||
| 362 | * | ||
| 363 | ******************************************************************************/ | ||
| 364 | |||
| 365 | static void | ||
| 366 | acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | ||
| 367 | struct acpi_evaluate_info *info) | ||
| 368 | { | ||
| 369 | union acpi_operand_object *root_obj; | ||
| 370 | acpi_status status; | ||
| 371 | |||
| 372 | ACPI_FUNCTION_TRACE(ns_exec_module_code); | ||
| 373 | |||
| 374 | /* Initialize the evaluation information block */ | ||
| 375 | |||
| 376 | ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); | ||
| 377 | info->prefix_node = acpi_gbl_root_node; | ||
| 378 | |||
| 379 | /* | ||
| 380 | * Get the currently attached root object. Add a reference, because the | ||
| 381 | * ref count will be decreased when the method object is installed to | ||
| 382 | * the root node. | ||
| 383 | */ | ||
| 384 | root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node); | ||
| 385 | acpi_ut_add_reference(root_obj); | ||
| 386 | |||
| 387 | /* Install the method (module-level code) in the root node */ | ||
| 388 | |||
| 389 | status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj, | ||
| 390 | ACPI_TYPE_METHOD); | ||
| 391 | if (ACPI_FAILURE(status)) { | ||
| 392 | goto exit; | ||
| 393 | } | ||
| 394 | |||
| 395 | /* Execute the root node as a control method */ | ||
| 396 | |||
| 397 | status = acpi_ns_evaluate(info); | ||
| 398 | |||
| 399 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", | ||
| 400 | method_obj->method.aml_start)); | ||
| 401 | |||
| 402 | /* Detach the temporary method object */ | ||
| 403 | |||
| 404 | acpi_ns_detach_object(acpi_gbl_root_node); | ||
| 405 | |||
| 406 | /* Restore the original root object */ | ||
| 407 | |||
| 408 | status = | ||
| 409 | acpi_ns_attach_object(acpi_gbl_root_node, root_obj, | ||
| 410 | ACPI_TYPE_DEVICE); | ||
| 411 | |||
| 412 | exit: | ||
| 413 | acpi_ut_remove_reference(root_obj); | ||
| 414 | return_VOID; | ||
| 415 | } | ||
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 2adfcf329e15..1d5b360eb25b 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c | |||
| @@ -170,6 +170,21 @@ acpi_status acpi_ns_initialize_devices(void) | |||
| 170 | goto error_exit; | 170 | goto error_exit; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | /* | ||
| 174 | * Execute the "global" _INI method that may appear at the root. This | ||
| 175 | * support is provided for Windows compatibility (Vista+) and is not | ||
| 176 | * part of the ACPI specification. | ||
| 177 | */ | ||
| 178 | info.evaluate_info->prefix_node = acpi_gbl_root_node; | ||
| 179 | info.evaluate_info->pathname = METHOD_NAME__INI; | ||
| 180 | info.evaluate_info->parameters = NULL; | ||
| 181 | info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE; | ||
| 182 | |||
| 183 | status = acpi_ns_evaluate(info.evaluate_info); | ||
| 184 | if (ACPI_SUCCESS(status)) { | ||
| 185 | info.num_INI++; | ||
| 186 | } | ||
| 187 | |||
| 173 | /* Walk namespace to execute all _INIs on present devices */ | 188 | /* Walk namespace to execute all _INIs on present devices */ |
| 174 | 189 | ||
| 175 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 190 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, |
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index dcd7a6adbbbc..a7234e60e985 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c | |||
| @@ -270,8 +270,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) | |||
| 270 | 270 | ||
| 271 | /* Now delete the starting object, and we are done */ | 271 | /* Now delete the starting object, and we are done */ |
| 272 | 272 | ||
| 273 | acpi_ns_delete_node(child_handle); | 273 | acpi_ns_remove_node(child_handle); |
| 274 | |||
| 275 | return_ACPI_STATUS(AE_OK); | 274 | return_ACPI_STATUS(AE_OK); |
| 276 | } | 275 | } |
| 277 | 276 | ||
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 7f8e066b12a3..f8427afeebdf 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
| @@ -42,6 +42,8 @@ | |||
| 42 | * POSSIBILITY OF SUCH DAMAGES. | 42 | * POSSIBILITY OF SUCH DAMAGES. |
| 43 | */ | 43 | */ |
| 44 | 44 | ||
| 45 | #define ACPI_CREATE_PREDEFINED_TABLE | ||
| 46 | |||
| 45 | #include <acpi/acpi.h> | 47 | #include <acpi/acpi.h> |
| 46 | #include "accommon.h" | 48 | #include "accommon.h" |
| 47 | #include "acnamesp.h" | 49 | #include "acnamesp.h" |
| @@ -72,30 +74,31 @@ ACPI_MODULE_NAME("nspredef") | |||
| 72 | ******************************************************************************/ | 74 | ******************************************************************************/ |
| 73 | /* Local prototypes */ | 75 | /* Local prototypes */ |
| 74 | static acpi_status | 76 | static acpi_status |
| 75 | acpi_ns_check_package(char *pathname, | 77 | acpi_ns_check_package(struct acpi_predefined_data *data, |
| 76 | union acpi_operand_object **return_object_ptr, | 78 | union acpi_operand_object **return_object_ptr); |
| 77 | const union acpi_predefined_info *predefined); | 79 | |
| 80 | static acpi_status | ||
| 81 | acpi_ns_check_package_list(struct acpi_predefined_data *data, | ||
| 82 | const union acpi_predefined_info *package, | ||
| 83 | union acpi_operand_object **elements, u32 count); | ||
| 78 | 84 | ||
| 79 | static acpi_status | 85 | static acpi_status |
| 80 | acpi_ns_check_package_elements(char *pathname, | 86 | acpi_ns_check_package_elements(struct acpi_predefined_data *data, |
| 81 | union acpi_operand_object **elements, | 87 | union acpi_operand_object **elements, |
| 82 | u8 type1, | 88 | u8 type1, |
| 83 | u32 count1, | 89 | u32 count1, |
| 84 | u8 type2, u32 count2, u32 start_index); | 90 | u8 type2, u32 count2, u32 start_index); |
| 85 | 91 | ||
| 86 | static acpi_status | 92 | static acpi_status |
| 87 | acpi_ns_check_object_type(char *pathname, | 93 | acpi_ns_check_object_type(struct acpi_predefined_data *data, |
| 88 | union acpi_operand_object **return_object_ptr, | 94 | union acpi_operand_object **return_object_ptr, |
| 89 | u32 expected_btypes, u32 package_index); | 95 | u32 expected_btypes, u32 package_index); |
| 90 | 96 | ||
| 91 | static acpi_status | 97 | static acpi_status |
| 92 | acpi_ns_check_reference(char *pathname, | 98 | acpi_ns_check_reference(struct acpi_predefined_data *data, |
| 93 | union acpi_operand_object *return_object); | 99 | union acpi_operand_object *return_object); |
| 94 | 100 | ||
| 95 | static acpi_status | 101 | static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes); |
| 96 | acpi_ns_repair_object(u32 expected_btypes, | ||
| 97 | u32 package_index, | ||
| 98 | union acpi_operand_object **return_object_ptr); | ||
| 99 | 102 | ||
| 100 | /* | 103 | /* |
| 101 | * Names for the types that can be returned by the predefined objects. | 104 | * Names for the types that can be returned by the predefined objects. |
| @@ -109,13 +112,13 @@ static const char *acpi_rtype_names[] = { | |||
| 109 | "/Reference", | 112 | "/Reference", |
| 110 | }; | 113 | }; |
| 111 | 114 | ||
| 112 | #define ACPI_NOT_PACKAGE ACPI_UINT32_MAX | ||
| 113 | |||
| 114 | /******************************************************************************* | 115 | /******************************************************************************* |
| 115 | * | 116 | * |
| 116 | * FUNCTION: acpi_ns_check_predefined_names | 117 | * FUNCTION: acpi_ns_check_predefined_names |
| 117 | * | 118 | * |
| 118 | * PARAMETERS: Node - Namespace node for the method/object | 119 | * PARAMETERS: Node - Namespace node for the method/object |
| 120 | * user_param_count - Number of parameters actually passed | ||
| 121 | * return_status - Status from the object evaluation | ||
| 119 | * return_object_ptr - Pointer to the object returned from the | 122 | * return_object_ptr - Pointer to the object returned from the |
| 120 | * evaluation of a method or object | 123 | * evaluation of a method or object |
| 121 | * | 124 | * |
| @@ -135,12 +138,13 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
| 135 | acpi_status status = AE_OK; | 138 | acpi_status status = AE_OK; |
| 136 | const union acpi_predefined_info *predefined; | 139 | const union acpi_predefined_info *predefined; |
| 137 | char *pathname; | 140 | char *pathname; |
| 141 | struct acpi_predefined_data *data; | ||
| 138 | 142 | ||
| 139 | /* Match the name for this method/object against the predefined list */ | 143 | /* Match the name for this method/object against the predefined list */ |
| 140 | 144 | ||
| 141 | predefined = acpi_ns_check_for_predefined_name(node); | 145 | predefined = acpi_ns_check_for_predefined_name(node); |
| 142 | 146 | ||
| 143 | /* Get the full pathname to the object, for use in error messages */ | 147 | /* Get the full pathname to the object, for use in warning messages */ |
| 144 | 148 | ||
| 145 | pathname = acpi_ns_get_external_pathname(node); | 149 | pathname = acpi_ns_get_external_pathname(node); |
| 146 | if (!pathname) { | 150 | if (!pathname) { |
| @@ -158,28 +162,17 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
| 158 | /* If not a predefined name, we cannot validate the return object */ | 162 | /* If not a predefined name, we cannot validate the return object */ |
| 159 | 163 | ||
| 160 | if (!predefined) { | 164 | if (!predefined) { |
| 161 | goto exit; | 165 | goto cleanup; |
| 162 | } | ||
| 163 | |||
| 164 | /* If the method failed, we cannot validate the return object */ | ||
| 165 | |||
| 166 | if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { | ||
| 167 | goto exit; | ||
| 168 | } | 166 | } |
| 169 | 167 | ||
| 170 | /* | 168 | /* |
| 171 | * Only validate the return value on the first successful evaluation of | 169 | * If the method failed or did not actually return an object, we cannot |
| 172 | * the method. This ensures that any warnings will only be emitted during | 170 | * validate the return object |
| 173 | * the very first evaluation of the method/object. | ||
| 174 | */ | 171 | */ |
| 175 | if (node->flags & ANOBJ_EVALUATED) { | 172 | if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { |
| 176 | goto exit; | 173 | goto cleanup; |
| 177 | } | 174 | } |
| 178 | 175 | ||
| 179 | /* Mark the node as having been successfully evaluated */ | ||
| 180 | |||
| 181 | node->flags |= ANOBJ_EVALUATED; | ||
| 182 | |||
| 183 | /* | 176 | /* |
| 184 | * If there is no return value, check if we require a return value for | 177 | * If there is no return value, check if we require a return value for |
| 185 | * this predefined name. Either one return value is expected, or none, | 178 | * this predefined name. Either one return value is expected, or none, |
| @@ -190,46 +183,67 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
| 190 | if (!return_object) { | 183 | if (!return_object) { |
| 191 | if ((predefined->info.expected_btypes) && | 184 | if ((predefined->info.expected_btypes) && |
| 192 | (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { | 185 | (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { |
| 193 | ACPI_ERROR((AE_INFO, | 186 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, |
| 194 | "%s: Missing expected return value", | 187 | ACPI_WARN_ALWAYS, |
| 195 | pathname)); | 188 | "Missing expected return value")); |
| 196 | 189 | ||
| 197 | status = AE_AML_NO_RETURN_VALUE; | 190 | status = AE_AML_NO_RETURN_VALUE; |
| 198 | } | 191 | } |
| 199 | goto exit; | 192 | goto cleanup; |
| 200 | } | 193 | } |
| 201 | 194 | ||
| 202 | /* | 195 | /* |
| 203 | * We have a return value, but if one wasn't expected, just exit, this is | 196 | * 1) We have a return value, but if one wasn't expected, just exit, this is |
| 204 | * not a problem | 197 | * not a problem. For example, if the "Implicit Return" feature is |
| 198 | * enabled, methods will always return a value. | ||
| 205 | * | 199 | * |
| 206 | * For example, if the "Implicit Return" feature is enabled, methods will | 200 | * 2) If the return value can be of any type, then we cannot perform any |
| 207 | * always return a value | 201 | * validation, exit. |
| 208 | */ | 202 | */ |
| 209 | if (!predefined->info.expected_btypes) { | 203 | if ((!predefined->info.expected_btypes) || |
| 210 | goto exit; | 204 | (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { |
| 205 | goto cleanup; | ||
| 211 | } | 206 | } |
| 212 | 207 | ||
| 208 | /* Create the parameter data block for object validation */ | ||
| 209 | |||
| 210 | data = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_predefined_data)); | ||
| 211 | if (!data) { | ||
| 212 | goto cleanup; | ||
| 213 | } | ||
| 214 | data->predefined = predefined; | ||
| 215 | data->node_flags = node->flags; | ||
| 216 | data->pathname = pathname; | ||
| 217 | |||
| 213 | /* | 218 | /* |
| 214 | * Check that the type of the return object is what is expected for | 219 | * Check that the type of the return object is what is expected for |
| 215 | * this predefined name | 220 | * this predefined name |
| 216 | */ | 221 | */ |
| 217 | status = acpi_ns_check_object_type(pathname, return_object_ptr, | 222 | status = acpi_ns_check_object_type(data, return_object_ptr, |
| 218 | predefined->info.expected_btypes, | 223 | predefined->info.expected_btypes, |
| 219 | ACPI_NOT_PACKAGE); | 224 | ACPI_NOT_PACKAGE_ELEMENT); |
| 220 | if (ACPI_FAILURE(status)) { | 225 | if (ACPI_FAILURE(status)) { |
| 221 | goto exit; | 226 | goto check_validation_status; |
| 222 | } | 227 | } |
| 223 | 228 | ||
| 224 | /* For returned Package objects, check the type of all sub-objects */ | 229 | /* For returned Package objects, check the type of all sub-objects */ |
| 225 | 230 | ||
| 226 | if (return_object->common.type == ACPI_TYPE_PACKAGE) { | 231 | if (return_object->common.type == ACPI_TYPE_PACKAGE) { |
| 227 | status = | 232 | status = acpi_ns_check_package(data, return_object_ptr); |
| 228 | acpi_ns_check_package(pathname, return_object_ptr, | 233 | } |
| 229 | predefined); | 234 | |
| 235 | check_validation_status: | ||
| 236 | /* | ||
| 237 | * If the object validation failed or if we successfully repaired one | ||
| 238 | * or more objects, mark the parent node to suppress further warning | ||
| 239 | * messages during the next evaluation of the same method/object. | ||
| 240 | */ | ||
| 241 | if (ACPI_FAILURE(status) || (data->flags & ACPI_OBJECT_REPAIRED)) { | ||
| 242 | node->flags |= ANOBJ_EVALUATED; | ||
| 230 | } | 243 | } |
| 244 | ACPI_FREE(data); | ||
| 231 | 245 | ||
| 232 | exit: | 246 | cleanup: |
| 233 | ACPI_FREE(pathname); | 247 | ACPI_FREE(pathname); |
| 234 | return (status); | 248 | return (status); |
| 235 | } | 249 | } |
| @@ -268,64 +282,58 @@ acpi_ns_check_parameter_count(char *pathname, | |||
| 268 | param_count = node->object->method.param_count; | 282 | param_count = node->object->method.param_count; |
| 269 | } | 283 | } |
| 270 | 284 | ||
| 271 | /* Argument count check for non-predefined methods/objects */ | ||
| 272 | |||
| 273 | if (!predefined) { | 285 | if (!predefined) { |
| 274 | /* | 286 | /* |
| 287 | * Check the parameter count for non-predefined methods/objects. | ||
| 288 | * | ||
| 275 | * Warning if too few or too many arguments have been passed by the | 289 | * Warning if too few or too many arguments have been passed by the |
| 276 | * caller. An incorrect number of arguments may not cause the method | 290 | * caller. An incorrect number of arguments may not cause the method |
| 277 | * to fail. However, the method will fail if there are too few | 291 | * to fail. However, the method will fail if there are too few |
| 278 | * arguments and the method attempts to use one of the missing ones. | 292 | * arguments and the method attempts to use one of the missing ones. |
| 279 | */ | 293 | */ |
| 280 | if (user_param_count < param_count) { | 294 | if (user_param_count < param_count) { |
| 281 | ACPI_WARNING((AE_INFO, | 295 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, |
| 282 | "%s: Insufficient arguments - needs %d, found %d", | 296 | ACPI_WARN_ALWAYS, |
| 283 | pathname, param_count, user_param_count)); | 297 | "Insufficient arguments - needs %u, found %u", |
| 298 | param_count, user_param_count)); | ||
| 284 | } else if (user_param_count > param_count) { | 299 | } else if (user_param_count > param_count) { |
| 285 | ACPI_WARNING((AE_INFO, | 300 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, |
| 286 | "%s: Excess arguments - needs %d, found %d", | 301 | ACPI_WARN_ALWAYS, |
| 287 | pathname, param_count, user_param_count)); | 302 | "Excess arguments - needs %u, found %u", |
| 303 | param_count, user_param_count)); | ||
| 288 | } | 304 | } |
| 289 | return; | 305 | return; |
| 290 | } | 306 | } |
| 291 | 307 | ||
| 292 | /* Allow two different legal argument counts (_SCP, etc.) */ | 308 | /* |
| 293 | 309 | * Validate the user-supplied parameter count. | |
| 310 | * Allow two different legal argument counts (_SCP, etc.) | ||
| 311 | */ | ||
| 294 | required_params_current = predefined->info.param_count & 0x0F; | 312 | required_params_current = predefined->info.param_count & 0x0F; |
| 295 | required_params_old = predefined->info.param_count >> 4; | 313 | required_params_old = predefined->info.param_count >> 4; |
| 296 | 314 | ||
| 297 | if (user_param_count != ACPI_UINT32_MAX) { | 315 | if (user_param_count != ACPI_UINT32_MAX) { |
| 298 | |||
| 299 | /* Validate the user-supplied parameter count */ | ||
| 300 | |||
| 301 | if ((user_param_count != required_params_current) && | 316 | if ((user_param_count != required_params_current) && |
| 302 | (user_param_count != required_params_old)) { | 317 | (user_param_count != required_params_old)) { |
| 303 | ACPI_WARNING((AE_INFO, | 318 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, |
| 304 | "%s: Parameter count mismatch - " | 319 | ACPI_WARN_ALWAYS, |
| 305 | "caller passed %d, ACPI requires %d", | 320 | "Parameter count mismatch - " |
| 306 | pathname, user_param_count, | 321 | "caller passed %u, ACPI requires %u", |
| 307 | required_params_current)); | 322 | user_param_count, |
| 323 | required_params_current)); | ||
| 308 | } | 324 | } |
| 309 | } | 325 | } |
| 310 | 326 | ||
| 311 | /* | 327 | /* |
| 312 | * Only validate the argument count on the first successful evaluation of | ||
| 313 | * the method. This ensures that any warnings will only be emitted during | ||
| 314 | * the very first evaluation of the method/object. | ||
| 315 | */ | ||
| 316 | if (node->flags & ANOBJ_EVALUATED) { | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | /* | ||
| 321 | * Check that the ASL-defined parameter count is what is expected for | 328 | * Check that the ASL-defined parameter count is what is expected for |
| 322 | * this predefined name. | 329 | * this predefined name (parameter count as defined by the ACPI |
| 330 | * specification) | ||
| 323 | */ | 331 | */ |
| 324 | if ((param_count != required_params_current) && | 332 | if ((param_count != required_params_current) && |
| 325 | (param_count != required_params_old)) { | 333 | (param_count != required_params_old)) { |
| 326 | ACPI_WARNING((AE_INFO, | 334 | ACPI_WARN_PREDEFINED((AE_INFO, pathname, node->flags, |
| 327 | "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d", | 335 | "Parameter count mismatch - ASL declared %u, ACPI requires %u", |
| 328 | pathname, param_count, required_params_current)); | 336 | param_count, required_params_current)); |
| 329 | } | 337 | } |
| 330 | } | 338 | } |
| 331 | 339 | ||
| @@ -358,9 +366,6 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct | |||
| 358 | this_name = predefined_names; | 366 | this_name = predefined_names; |
| 359 | while (this_name->info.name[0]) { | 367 | while (this_name->info.name[0]) { |
| 360 | if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { | 368 | if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { |
| 361 | |||
| 362 | /* Return pointer to this table entry */ | ||
| 363 | |||
| 364 | return (this_name); | 369 | return (this_name); |
| 365 | } | 370 | } |
| 366 | 371 | ||
| @@ -375,17 +380,16 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct | |||
| 375 | this_name++; | 380 | this_name++; |
| 376 | } | 381 | } |
| 377 | 382 | ||
| 378 | return (NULL); | 383 | return (NULL); /* Not found */ |
| 379 | } | 384 | } |
| 380 | 385 | ||
| 381 | /******************************************************************************* | 386 | /******************************************************************************* |
| 382 | * | 387 | * |
| 383 | * FUNCTION: acpi_ns_check_package | 388 | * FUNCTION: acpi_ns_check_package |
| 384 | * | 389 | * |
| 385 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | 390 | * PARAMETERS: Data - Pointer to validation data structure |
| 386 | * return_object_ptr - Pointer to the object returned from the | 391 | * return_object_ptr - Pointer to the object returned from the |
| 387 | * evaluation of a method or object | 392 | * evaluation of a method or object |
| 388 | * Predefined - Pointer to entry in predefined name table | ||
| 389 | * | 393 | * |
| 390 | * RETURN: Status | 394 | * RETURN: Status |
| 391 | * | 395 | * |
| @@ -395,30 +399,26 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct | |||
| 395 | ******************************************************************************/ | 399 | ******************************************************************************/ |
| 396 | 400 | ||
| 397 | static acpi_status | 401 | static acpi_status |
| 398 | acpi_ns_check_package(char *pathname, | 402 | acpi_ns_check_package(struct acpi_predefined_data *data, |
| 399 | union acpi_operand_object **return_object_ptr, | 403 | union acpi_operand_object **return_object_ptr) |
| 400 | const union acpi_predefined_info *predefined) | ||
| 401 | { | 404 | { |
| 402 | union acpi_operand_object *return_object = *return_object_ptr; | 405 | union acpi_operand_object *return_object = *return_object_ptr; |
| 403 | const union acpi_predefined_info *package; | 406 | const union acpi_predefined_info *package; |
| 404 | union acpi_operand_object *sub_package; | ||
| 405 | union acpi_operand_object **elements; | 407 | union acpi_operand_object **elements; |
| 406 | union acpi_operand_object **sub_elements; | 408 | acpi_status status = AE_OK; |
| 407 | acpi_status status; | ||
| 408 | u32 expected_count; | 409 | u32 expected_count; |
| 409 | u32 count; | 410 | u32 count; |
| 410 | u32 i; | 411 | u32 i; |
| 411 | u32 j; | ||
| 412 | 412 | ||
| 413 | ACPI_FUNCTION_NAME(ns_check_package); | 413 | ACPI_FUNCTION_NAME(ns_check_package); |
| 414 | 414 | ||
| 415 | /* The package info for this name is in the next table entry */ | 415 | /* The package info for this name is in the next table entry */ |
| 416 | 416 | ||
| 417 | package = predefined + 1; | 417 | package = data->predefined + 1; |
| 418 | 418 | ||
| 419 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, | 419 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
| 420 | "%s Validating return Package of Type %X, Count %X\n", | 420 | "%s Validating return Package of Type %X, Count %X\n", |
| 421 | pathname, package->ret_info.type, | 421 | data->pathname, package->ret_info.type, |
| 422 | return_object->package.count)); | 422 | return_object->package.count)); |
| 423 | 423 | ||
| 424 | /* Extract package count and elements array */ | 424 | /* Extract package count and elements array */ |
| @@ -429,9 +429,8 @@ acpi_ns_check_package(char *pathname, | |||
| 429 | /* The package must have at least one element, else invalid */ | 429 | /* The package must have at least one element, else invalid */ |
| 430 | 430 | ||
| 431 | if (!count) { | 431 | if (!count) { |
| 432 | ACPI_WARNING((AE_INFO, | 432 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 433 | "%s: Return Package has no elements (empty)", | 433 | "Return Package has no elements (empty)")); |
| 434 | pathname)); | ||
| 435 | 434 | ||
| 436 | return (AE_AML_OPERAND_VALUE); | 435 | return (AE_AML_OPERAND_VALUE); |
| 437 | } | 436 | } |
| @@ -456,15 +455,16 @@ acpi_ns_check_package(char *pathname, | |||
| 456 | if (count < expected_count) { | 455 | if (count < expected_count) { |
| 457 | goto package_too_small; | 456 | goto package_too_small; |
| 458 | } else if (count > expected_count) { | 457 | } else if (count > expected_count) { |
| 459 | ACPI_WARNING((AE_INFO, | 458 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, |
| 460 | "%s: Return Package is larger than needed - " | 459 | data->node_flags, |
| 461 | "found %u, expected %u", pathname, count, | 460 | "Return Package is larger than needed - " |
| 462 | expected_count)); | 461 | "found %u, expected %u", count, |
| 462 | expected_count)); | ||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | /* Validate all elements of the returned package */ | 465 | /* Validate all elements of the returned package */ |
| 466 | 466 | ||
| 467 | status = acpi_ns_check_package_elements(pathname, elements, | 467 | status = acpi_ns_check_package_elements(data, elements, |
| 468 | package->ret_info. | 468 | package->ret_info. |
| 469 | object_type1, | 469 | object_type1, |
| 470 | package->ret_info. | 470 | package->ret_info. |
| @@ -473,9 +473,6 @@ acpi_ns_check_package(char *pathname, | |||
| 473 | object_type2, | 473 | object_type2, |
| 474 | package->ret_info. | 474 | package->ret_info. |
| 475 | count2, 0); | 475 | count2, 0); |
| 476 | if (ACPI_FAILURE(status)) { | ||
| 477 | return (status); | ||
| 478 | } | ||
| 479 | break; | 476 | break; |
| 480 | 477 | ||
| 481 | case ACPI_PTYPE1_VAR: | 478 | case ACPI_PTYPE1_VAR: |
| @@ -485,7 +482,7 @@ acpi_ns_check_package(char *pathname, | |||
| 485 | * elements must be of the same type | 482 | * elements must be of the same type |
| 486 | */ | 483 | */ |
| 487 | for (i = 0; i < count; i++) { | 484 | for (i = 0; i < count; i++) { |
| 488 | status = acpi_ns_check_object_type(pathname, elements, | 485 | status = acpi_ns_check_object_type(data, elements, |
| 489 | package->ret_info. | 486 | package->ret_info. |
| 490 | object_type1, i); | 487 | object_type1, i); |
| 491 | if (ACPI_FAILURE(status)) { | 488 | if (ACPI_FAILURE(status)) { |
| @@ -517,8 +514,7 @@ acpi_ns_check_package(char *pathname, | |||
| 517 | /* These are the required package elements (0, 1, or 2) */ | 514 | /* These are the required package elements (0, 1, or 2) */ |
| 518 | 515 | ||
| 519 | status = | 516 | status = |
| 520 | acpi_ns_check_object_type(pathname, | 517 | acpi_ns_check_object_type(data, elements, |
| 521 | elements, | ||
| 522 | package-> | 518 | package-> |
| 523 | ret_info3. | 519 | ret_info3. |
| 524 | object_type[i], | 520 | object_type[i], |
| @@ -530,8 +526,7 @@ acpi_ns_check_package(char *pathname, | |||
| 530 | /* These are the optional package elements */ | 526 | /* These are the optional package elements */ |
| 531 | 527 | ||
| 532 | status = | 528 | status = |
| 533 | acpi_ns_check_object_type(pathname, | 529 | acpi_ns_check_object_type(data, elements, |
| 534 | elements, | ||
| 535 | package-> | 530 | package-> |
| 536 | ret_info3. | 531 | ret_info3. |
| 537 | tail_object_type, | 532 | tail_object_type, |
| @@ -544,11 +539,30 @@ acpi_ns_check_package(char *pathname, | |||
| 544 | } | 539 | } |
| 545 | break; | 540 | break; |
| 546 | 541 | ||
| 542 | case ACPI_PTYPE2_REV_FIXED: | ||
| 543 | |||
| 544 | /* First element is the (Integer) revision */ | ||
| 545 | |||
| 546 | status = acpi_ns_check_object_type(data, elements, | ||
| 547 | ACPI_RTYPE_INTEGER, 0); | ||
| 548 | if (ACPI_FAILURE(status)) { | ||
| 549 | return (status); | ||
| 550 | } | ||
| 551 | |||
| 552 | elements++; | ||
| 553 | count--; | ||
| 554 | |||
| 555 | /* Examine the sub-packages */ | ||
| 556 | |||
| 557 | status = | ||
| 558 | acpi_ns_check_package_list(data, package, elements, count); | ||
| 559 | break; | ||
| 560 | |||
| 547 | case ACPI_PTYPE2_PKG_COUNT: | 561 | case ACPI_PTYPE2_PKG_COUNT: |
| 548 | 562 | ||
| 549 | /* First element is the (Integer) count of sub-packages to follow */ | 563 | /* First element is the (Integer) count of sub-packages to follow */ |
| 550 | 564 | ||
| 551 | status = acpi_ns_check_object_type(pathname, elements, | 565 | status = acpi_ns_check_object_type(data, elements, |
| 552 | ACPI_RTYPE_INTEGER, 0); | 566 | ACPI_RTYPE_INTEGER, 0); |
| 553 | if (ACPI_FAILURE(status)) { | 567 | if (ACPI_FAILURE(status)) { |
| 554 | return (status); | 568 | return (status); |
| @@ -566,9 +580,11 @@ acpi_ns_check_package(char *pathname, | |||
| 566 | count = expected_count; | 580 | count = expected_count; |
| 567 | elements++; | 581 | elements++; |
| 568 | 582 | ||
| 569 | /* Now we can walk the sub-packages */ | 583 | /* Examine the sub-packages */ |
| 570 | 584 | ||
| 571 | /*lint -fallthrough */ | 585 | status = |
| 586 | acpi_ns_check_package_list(data, package, elements, count); | ||
| 587 | break; | ||
| 572 | 588 | ||
| 573 | case ACPI_PTYPE2: | 589 | case ACPI_PTYPE2: |
| 574 | case ACPI_PTYPE2_FIXED: | 590 | case ACPI_PTYPE2_FIXED: |
| @@ -576,176 +592,240 @@ acpi_ns_check_package(char *pathname, | |||
| 576 | case ACPI_PTYPE2_COUNT: | 592 | case ACPI_PTYPE2_COUNT: |
| 577 | 593 | ||
| 578 | /* | 594 | /* |
| 579 | * These types all return a single package that consists of a variable | 595 | * These types all return a single Package that consists of a |
| 580 | * number of sub-packages | 596 | * variable number of sub-Packages. |
| 597 | * | ||
| 598 | * First, ensure that the first element is a sub-Package. If not, | ||
| 599 | * the BIOS may have incorrectly returned the object as a single | ||
| 600 | * package instead of a Package of Packages (a common error if | ||
| 601 | * there is only one entry). We may be able to repair this by | ||
| 602 | * wrapping the returned Package with a new outer Package. | ||
| 581 | */ | 603 | */ |
| 582 | for (i = 0; i < count; i++) { | 604 | if ((*elements)->common.type != ACPI_TYPE_PACKAGE) { |
| 583 | sub_package = *elements; | ||
| 584 | sub_elements = sub_package->package.elements; | ||
| 585 | 605 | ||
| 586 | /* Each sub-object must be of type Package */ | 606 | /* Create the new outer package and populate it */ |
| 587 | 607 | ||
| 588 | status = | 608 | status = |
| 589 | acpi_ns_check_object_type(pathname, &sub_package, | 609 | acpi_ns_repair_package_list(data, |
| 590 | ACPI_RTYPE_PACKAGE, i); | 610 | return_object_ptr); |
| 591 | if (ACPI_FAILURE(status)) { | 611 | if (ACPI_FAILURE(status)) { |
| 592 | return (status); | 612 | return (status); |
| 593 | } | 613 | } |
| 594 | 614 | ||
| 595 | /* Examine the different types of sub-packages */ | 615 | /* Update locals to point to the new package (of 1 element) */ |
| 596 | 616 | ||
| 597 | switch (package->ret_info.type) { | 617 | return_object = *return_object_ptr; |
| 598 | case ACPI_PTYPE2: | 618 | elements = return_object->package.elements; |
| 599 | case ACPI_PTYPE2_PKG_COUNT: | 619 | count = 1; |
| 620 | } | ||
| 600 | 621 | ||
| 601 | /* Each subpackage has a fixed number of elements */ | 622 | /* Examine the sub-packages */ |
| 602 | 623 | ||
| 603 | expected_count = | 624 | status = |
| 604 | package->ret_info.count1 + | 625 | acpi_ns_check_package_list(data, package, elements, count); |
| 605 | package->ret_info.count2; | 626 | break; |
| 606 | if (sub_package->package.count != | ||
| 607 | expected_count) { | ||
| 608 | count = sub_package->package.count; | ||
| 609 | goto package_too_small; | ||
| 610 | } | ||
| 611 | 627 | ||
| 612 | status = | 628 | default: |
| 613 | acpi_ns_check_package_elements(pathname, | ||
| 614 | sub_elements, | ||
| 615 | package-> | ||
| 616 | ret_info. | ||
| 617 | object_type1, | ||
| 618 | package-> | ||
| 619 | ret_info. | ||
| 620 | count1, | ||
| 621 | package-> | ||
| 622 | ret_info. | ||
| 623 | object_type2, | ||
| 624 | package-> | ||
| 625 | ret_info. | ||
| 626 | count2, 0); | ||
| 627 | if (ACPI_FAILURE(status)) { | ||
| 628 | return (status); | ||
| 629 | } | ||
| 630 | break; | ||
| 631 | 629 | ||
| 632 | case ACPI_PTYPE2_FIXED: | 630 | /* Should not get here if predefined info table is correct */ |
| 633 | 631 | ||
| 634 | /* Each sub-package has a fixed length */ | 632 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 633 | "Invalid internal return type in table entry: %X", | ||
| 634 | package->ret_info.type)); | ||
| 635 | 635 | ||
| 636 | expected_count = package->ret_info2.count; | 636 | return (AE_AML_INTERNAL); |
| 637 | if (sub_package->package.count < expected_count) { | 637 | } |
| 638 | count = sub_package->package.count; | ||
| 639 | goto package_too_small; | ||
| 640 | } | ||
| 641 | 638 | ||
| 642 | /* Check the type of each sub-package element */ | 639 | return (status); |
| 643 | 640 | ||
| 644 | for (j = 0; j < expected_count; j++) { | 641 | package_too_small: |
| 645 | status = | ||
| 646 | acpi_ns_check_object_type(pathname, | ||
| 647 | &sub_elements[j], | ||
| 648 | package->ret_info2.object_type[j], j); | ||
| 649 | if (ACPI_FAILURE(status)) { | ||
| 650 | return (status); | ||
| 651 | } | ||
| 652 | } | ||
| 653 | break; | ||
| 654 | 642 | ||
| 655 | case ACPI_PTYPE2_MIN: | 643 | /* Error exit for the case with an incorrect package count */ |
| 656 | 644 | ||
| 657 | /* Each sub-package has a variable but minimum length */ | 645 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 646 | "Return Package is too small - found %u elements, expected %u", | ||
| 647 | count, expected_count)); | ||
| 658 | 648 | ||
| 659 | expected_count = package->ret_info.count1; | 649 | return (AE_AML_OPERAND_VALUE); |
| 660 | if (sub_package->package.count < expected_count) { | 650 | } |
| 661 | count = sub_package->package.count; | ||
| 662 | goto package_too_small; | ||
| 663 | } | ||
| 664 | 651 | ||
| 665 | /* Check the type of each sub-package element */ | 652 | /******************************************************************************* |
| 653 | * | ||
| 654 | * FUNCTION: acpi_ns_check_package_list | ||
| 655 | * | ||
| 656 | * PARAMETERS: Data - Pointer to validation data structure | ||
| 657 | * Package - Pointer to package-specific info for method | ||
| 658 | * Elements - Element list of parent package. All elements | ||
| 659 | * of this list should be of type Package. | ||
| 660 | * Count - Count of subpackages | ||
| 661 | * | ||
| 662 | * RETURN: Status | ||
| 663 | * | ||
| 664 | * DESCRIPTION: Examine a list of subpackages | ||
| 665 | * | ||
| 666 | ******************************************************************************/ | ||
| 666 | 667 | ||
| 667 | status = | 668 | static acpi_status |
| 668 | acpi_ns_check_package_elements(pathname, | 669 | acpi_ns_check_package_list(struct acpi_predefined_data *data, |
| 669 | sub_elements, | 670 | const union acpi_predefined_info *package, |
| 670 | package-> | 671 | union acpi_operand_object **elements, u32 count) |
| 671 | ret_info. | 672 | { |
| 672 | object_type1, | 673 | union acpi_operand_object *sub_package; |
| 673 | sub_package-> | 674 | union acpi_operand_object **sub_elements; |
| 674 | package. | 675 | acpi_status status; |
| 675 | count, 0, 0, | 676 | u32 expected_count; |
| 676 | 0); | 677 | u32 i; |
| 677 | if (ACPI_FAILURE(status)) { | 678 | u32 j; |
| 678 | return (status); | ||
| 679 | } | ||
| 680 | break; | ||
| 681 | 679 | ||
| 682 | case ACPI_PTYPE2_COUNT: | 680 | /* Validate each sub-Package in the parent Package */ |
| 683 | 681 | ||
| 684 | /* First element is the (Integer) count of elements to follow */ | 682 | for (i = 0; i < count; i++) { |
| 683 | sub_package = *elements; | ||
| 684 | sub_elements = sub_package->package.elements; | ||
| 685 | 685 | ||
| 686 | status = | 686 | /* Each sub-object must be of type Package */ |
| 687 | acpi_ns_check_object_type(pathname, | ||
| 688 | sub_elements, | ||
| 689 | ACPI_RTYPE_INTEGER, | ||
| 690 | 0); | ||
| 691 | if (ACPI_FAILURE(status)) { | ||
| 692 | return (status); | ||
| 693 | } | ||
| 694 | 687 | ||
| 695 | /* Make sure package is large enough for the Count */ | 688 | status = acpi_ns_check_object_type(data, &sub_package, |
| 689 | ACPI_RTYPE_PACKAGE, i); | ||
| 690 | if (ACPI_FAILURE(status)) { | ||
| 691 | return (status); | ||
| 692 | } | ||
| 696 | 693 | ||
| 697 | expected_count = | 694 | /* Examine the different types of expected sub-packages */ |
| 698 | (u32) (*sub_elements)->integer.value; | 695 | |
| 699 | if (sub_package->package.count < expected_count) { | 696 | switch (package->ret_info.type) { |
| 700 | count = sub_package->package.count; | 697 | case ACPI_PTYPE2: |
| 701 | goto package_too_small; | 698 | case ACPI_PTYPE2_PKG_COUNT: |
| 702 | } | 699 | case ACPI_PTYPE2_REV_FIXED: |
| 700 | |||
| 701 | /* Each subpackage has a fixed number of elements */ | ||
| 702 | |||
| 703 | expected_count = | ||
| 704 | package->ret_info.count1 + package->ret_info.count2; | ||
| 705 | if (sub_package->package.count < expected_count) { | ||
| 706 | goto package_too_small; | ||
| 707 | } | ||
| 708 | |||
| 709 | status = | ||
| 710 | acpi_ns_check_package_elements(data, sub_elements, | ||
| 711 | package->ret_info. | ||
| 712 | object_type1, | ||
| 713 | package->ret_info. | ||
| 714 | count1, | ||
| 715 | package->ret_info. | ||
| 716 | object_type2, | ||
| 717 | package->ret_info. | ||
| 718 | count2, 0); | ||
| 719 | if (ACPI_FAILURE(status)) { | ||
| 720 | return (status); | ||
| 721 | } | ||
| 722 | break; | ||
| 703 | 723 | ||
| 704 | /* Check the type of each sub-package element */ | 724 | case ACPI_PTYPE2_FIXED: |
| 705 | 725 | ||
| 726 | /* Each sub-package has a fixed length */ | ||
| 727 | |||
| 728 | expected_count = package->ret_info2.count; | ||
| 729 | if (sub_package->package.count < expected_count) { | ||
| 730 | goto package_too_small; | ||
| 731 | } | ||
| 732 | |||
| 733 | /* Check the type of each sub-package element */ | ||
| 734 | |||
| 735 | for (j = 0; j < expected_count; j++) { | ||
| 706 | status = | 736 | status = |
| 707 | acpi_ns_check_package_elements(pathname, | 737 | acpi_ns_check_object_type(data, |
| 708 | (sub_elements | 738 | &sub_elements[j], |
| 709 | + 1), | 739 | package-> |
| 710 | package-> | 740 | ret_info2. |
| 711 | ret_info. | 741 | object_type[j], |
| 712 | object_type1, | 742 | j); |
| 713 | (expected_count | ||
| 714 | - 1), 0, 0, | ||
| 715 | 1); | ||
| 716 | if (ACPI_FAILURE(status)) { | 743 | if (ACPI_FAILURE(status)) { |
| 717 | return (status); | 744 | return (status); |
| 718 | } | 745 | } |
| 719 | break; | 746 | } |
| 747 | break; | ||
| 748 | |||
| 749 | case ACPI_PTYPE2_MIN: | ||
| 720 | 750 | ||
| 721 | default: | 751 | /* Each sub-package has a variable but minimum length */ |
| 722 | break; | 752 | |
| 753 | expected_count = package->ret_info.count1; | ||
| 754 | if (sub_package->package.count < expected_count) { | ||
| 755 | goto package_too_small; | ||
| 723 | } | 756 | } |
| 724 | 757 | ||
| 725 | elements++; | 758 | /* Check the type of each sub-package element */ |
| 726 | } | ||
| 727 | break; | ||
| 728 | 759 | ||
| 729 | default: | 760 | status = |
| 761 | acpi_ns_check_package_elements(data, sub_elements, | ||
| 762 | package->ret_info. | ||
| 763 | object_type1, | ||
| 764 | sub_package->package. | ||
| 765 | count, 0, 0, 0); | ||
| 766 | if (ACPI_FAILURE(status)) { | ||
| 767 | return (status); | ||
| 768 | } | ||
| 769 | break; | ||
| 730 | 770 | ||
| 731 | /* Should not get here if predefined info table is correct */ | 771 | case ACPI_PTYPE2_COUNT: |
| 772 | |||
| 773 | /* | ||
| 774 | * First element is the (Integer) count of elements, including | ||
| 775 | * the count field. | ||
| 776 | */ | ||
| 777 | status = acpi_ns_check_object_type(data, sub_elements, | ||
| 778 | ACPI_RTYPE_INTEGER, | ||
| 779 | 0); | ||
| 780 | if (ACPI_FAILURE(status)) { | ||
| 781 | return (status); | ||
| 782 | } | ||
| 732 | 783 | ||
| 733 | ACPI_WARNING((AE_INFO, | 784 | /* |
| 734 | "%s: Invalid internal return type in table entry: %X", | 785 | * Make sure package is large enough for the Count and is |
| 735 | pathname, package->ret_info.type)); | 786 | * is as large as the minimum size |
| 787 | */ | ||
| 788 | expected_count = (u32)(*sub_elements)->integer.value; | ||
| 789 | if (sub_package->package.count < expected_count) { | ||
| 790 | goto package_too_small; | ||
| 791 | } | ||
| 792 | if (sub_package->package.count < | ||
| 793 | package->ret_info.count1) { | ||
| 794 | expected_count = package->ret_info.count1; | ||
| 795 | goto package_too_small; | ||
| 796 | } | ||
| 736 | 797 | ||
| 737 | return (AE_AML_INTERNAL); | 798 | /* Check the type of each sub-package element */ |
| 799 | |||
| 800 | status = | ||
| 801 | acpi_ns_check_package_elements(data, | ||
| 802 | (sub_elements + 1), | ||
| 803 | package->ret_info. | ||
| 804 | object_type1, | ||
| 805 | (expected_count - 1), | ||
| 806 | 0, 0, 1); | ||
| 807 | if (ACPI_FAILURE(status)) { | ||
| 808 | return (status); | ||
| 809 | } | ||
| 810 | break; | ||
| 811 | |||
| 812 | default: /* Should not get here, type was validated by caller */ | ||
| 813 | |||
| 814 | return (AE_AML_INTERNAL); | ||
| 815 | } | ||
| 816 | |||
| 817 | elements++; | ||
| 738 | } | 818 | } |
| 739 | 819 | ||
| 740 | return (AE_OK); | 820 | return (AE_OK); |
| 741 | 821 | ||
| 742 | package_too_small: | 822 | package_too_small: |
| 743 | 823 | ||
| 744 | /* Error exit for the case with an incorrect package count */ | 824 | /* The sub-package count was smaller than required */ |
| 745 | 825 | ||
| 746 | ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " | 826 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 747 | "found %u, expected %u", pathname, count, | 827 | "Return Sub-Package[%u] is too small - found %u elements, expected %u", |
| 748 | expected_count)); | 828 | i, sub_package->package.count, expected_count)); |
| 749 | 829 | ||
| 750 | return (AE_AML_OPERAND_VALUE); | 830 | return (AE_AML_OPERAND_VALUE); |
| 751 | } | 831 | } |
| @@ -754,7 +834,7 @@ acpi_ns_check_package(char *pathname, | |||
| 754 | * | 834 | * |
| 755 | * FUNCTION: acpi_ns_check_package_elements | 835 | * FUNCTION: acpi_ns_check_package_elements |
| 756 | * | 836 | * |
| 757 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | 837 | * PARAMETERS: Data - Pointer to validation data structure |
| 758 | * Elements - Pointer to the package elements array | 838 | * Elements - Pointer to the package elements array |
| 759 | * Type1 - Object type for first group | 839 | * Type1 - Object type for first group |
| 760 | * Count1 - Count for first group | 840 | * Count1 - Count for first group |
| @@ -770,7 +850,7 @@ acpi_ns_check_package(char *pathname, | |||
| 770 | ******************************************************************************/ | 850 | ******************************************************************************/ |
| 771 | 851 | ||
| 772 | static acpi_status | 852 | static acpi_status |
| 773 | acpi_ns_check_package_elements(char *pathname, | 853 | acpi_ns_check_package_elements(struct acpi_predefined_data *data, |
| 774 | union acpi_operand_object **elements, | 854 | union acpi_operand_object **elements, |
| 775 | u8 type1, | 855 | u8 type1, |
| 776 | u32 count1, | 856 | u32 count1, |
| @@ -786,7 +866,7 @@ acpi_ns_check_package_elements(char *pathname, | |||
| 786 | * The second group can have a count of zero. | 866 | * The second group can have a count of zero. |
| 787 | */ | 867 | */ |
| 788 | for (i = 0; i < count1; i++) { | 868 | for (i = 0; i < count1; i++) { |
| 789 | status = acpi_ns_check_object_type(pathname, this_element, | 869 | status = acpi_ns_check_object_type(data, this_element, |
| 790 | type1, i + start_index); | 870 | type1, i + start_index); |
| 791 | if (ACPI_FAILURE(status)) { | 871 | if (ACPI_FAILURE(status)) { |
| 792 | return (status); | 872 | return (status); |
| @@ -795,7 +875,7 @@ acpi_ns_check_package_elements(char *pathname, | |||
| 795 | } | 875 | } |
| 796 | 876 | ||
| 797 | for (i = 0; i < count2; i++) { | 877 | for (i = 0; i < count2; i++) { |
| 798 | status = acpi_ns_check_object_type(pathname, this_element, | 878 | status = acpi_ns_check_object_type(data, this_element, |
| 799 | type2, | 879 | type2, |
| 800 | (i + count1 + start_index)); | 880 | (i + count1 + start_index)); |
| 801 | if (ACPI_FAILURE(status)) { | 881 | if (ACPI_FAILURE(status)) { |
| @@ -811,12 +891,13 @@ acpi_ns_check_package_elements(char *pathname, | |||
| 811 | * | 891 | * |
| 812 | * FUNCTION: acpi_ns_check_object_type | 892 | * FUNCTION: acpi_ns_check_object_type |
| 813 | * | 893 | * |
| 814 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | 894 | * PARAMETERS: Data - Pointer to validation data structure |
| 815 | * return_object_ptr - Pointer to the object returned from the | 895 | * return_object_ptr - Pointer to the object returned from the |
| 816 | * evaluation of a method or object | 896 | * evaluation of a method or object |
| 817 | * expected_btypes - Bitmap of expected return type(s) | 897 | * expected_btypes - Bitmap of expected return type(s) |
| 818 | * package_index - Index of object within parent package (if | 898 | * package_index - Index of object within parent package (if |
| 819 | * applicable - ACPI_NOT_PACKAGE otherwise) | 899 | * applicable - ACPI_NOT_PACKAGE_ELEMENT |
| 900 | * otherwise) | ||
| 820 | * | 901 | * |
| 821 | * RETURN: Status | 902 | * RETURN: Status |
| 822 | * | 903 | * |
| @@ -826,7 +907,7 @@ acpi_ns_check_package_elements(char *pathname, | |||
| 826 | ******************************************************************************/ | 907 | ******************************************************************************/ |
| 827 | 908 | ||
| 828 | static acpi_status | 909 | static acpi_status |
| 829 | acpi_ns_check_object_type(char *pathname, | 910 | acpi_ns_check_object_type(struct acpi_predefined_data *data, |
| 830 | union acpi_operand_object **return_object_ptr, | 911 | union acpi_operand_object **return_object_ptr, |
| 831 | u32 expected_btypes, u32 package_index) | 912 | u32 expected_btypes, u32 package_index) |
| 832 | { | 913 | { |
| @@ -834,9 +915,6 @@ acpi_ns_check_object_type(char *pathname, | |||
| 834 | acpi_status status = AE_OK; | 915 | acpi_status status = AE_OK; |
| 835 | u32 return_btype; | 916 | u32 return_btype; |
| 836 | char type_buffer[48]; /* Room for 5 types */ | 917 | char type_buffer[48]; /* Room for 5 types */ |
| 837 | u32 this_rtype; | ||
| 838 | u32 i; | ||
| 839 | u32 j; | ||
| 840 | 918 | ||
| 841 | /* | 919 | /* |
| 842 | * If we get a NULL return_object here, it is a NULL package element, | 920 | * If we get a NULL return_object here, it is a NULL package element, |
| @@ -849,10 +927,11 @@ acpi_ns_check_object_type(char *pathname, | |||
| 849 | /* A Namespace node should not get here, but make sure */ | 927 | /* A Namespace node should not get here, but make sure */ |
| 850 | 928 | ||
| 851 | if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { | 929 | if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { |
| 852 | ACPI_WARNING((AE_INFO, | 930 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 853 | "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", | 931 | "Invalid return type - Found a Namespace node [%4.4s] type %s", |
| 854 | pathname, return_object->node.name.ascii, | 932 | return_object->node.name.ascii, |
| 855 | acpi_ut_get_type_name(return_object->node.type))); | 933 | acpi_ut_get_type_name(return_object->node. |
| 934 | type))); | ||
| 856 | return (AE_AML_OPERAND_TYPE); | 935 | return (AE_AML_OPERAND_TYPE); |
| 857 | } | 936 | } |
| 858 | 937 | ||
| @@ -897,10 +976,11 @@ acpi_ns_check_object_type(char *pathname, | |||
| 897 | 976 | ||
| 898 | /* Type mismatch -- attempt repair of the returned object */ | 977 | /* Type mismatch -- attempt repair of the returned object */ |
| 899 | 978 | ||
| 900 | status = acpi_ns_repair_object(expected_btypes, package_index, | 979 | status = acpi_ns_repair_object(data, expected_btypes, |
| 980 | package_index, | ||
| 901 | return_object_ptr); | 981 | return_object_ptr); |
| 902 | if (ACPI_SUCCESS(status)) { | 982 | if (ACPI_SUCCESS(status)) { |
| 903 | return (status); | 983 | return (AE_OK); /* Repair was successful */ |
| 904 | } | 984 | } |
| 905 | goto type_error_exit; | 985 | goto type_error_exit; |
| 906 | } | 986 | } |
| @@ -908,7 +988,7 @@ acpi_ns_check_object_type(char *pathname, | |||
| 908 | /* For reference objects, check that the reference type is correct */ | 988 | /* For reference objects, check that the reference type is correct */ |
| 909 | 989 | ||
| 910 | if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { | 990 | if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { |
| 911 | status = acpi_ns_check_reference(pathname, return_object); | 991 | status = acpi_ns_check_reference(data, return_object); |
| 912 | } | 992 | } |
| 913 | 993 | ||
| 914 | return (status); | 994 | return (status); |
| @@ -917,33 +997,19 @@ acpi_ns_check_object_type(char *pathname, | |||
| 917 | 997 | ||
| 918 | /* Create a string with all expected types for this predefined object */ | 998 | /* Create a string with all expected types for this predefined object */ |
| 919 | 999 | ||
| 920 | j = 1; | 1000 | acpi_ns_get_expected_types(type_buffer, expected_btypes); |
| 921 | type_buffer[0] = 0; | ||
| 922 | this_rtype = ACPI_RTYPE_INTEGER; | ||
| 923 | |||
| 924 | for (i = 0; i < ACPI_NUM_RTYPES; i++) { | ||
| 925 | |||
| 926 | /* If one of the expected types, concatenate the name of this type */ | ||
| 927 | |||
| 928 | if (expected_btypes & this_rtype) { | ||
| 929 | ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); | ||
| 930 | j = 0; /* Use name separator from now on */ | ||
| 931 | } | ||
| 932 | this_rtype <<= 1; /* Next Rtype */ | ||
| 933 | } | ||
| 934 | 1001 | ||
| 935 | if (package_index == ACPI_NOT_PACKAGE) { | 1002 | if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { |
| 936 | ACPI_WARNING((AE_INFO, | 1003 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 937 | "%s: Return type mismatch - found %s, expected %s", | 1004 | "Return type mismatch - found %s, expected %s", |
| 938 | pathname, | 1005 | acpi_ut_get_object_type_name |
| 939 | acpi_ut_get_object_type_name(return_object), | 1006 | (return_object), type_buffer)); |
| 940 | type_buffer)); | ||
| 941 | } else { | 1007 | } else { |
| 942 | ACPI_WARNING((AE_INFO, | 1008 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 943 | "%s: Return Package type mismatch at index %u - " | 1009 | "Return Package type mismatch at index %u - " |
| 944 | "found %s, expected %s", pathname, package_index, | 1010 | "found %s, expected %s", package_index, |
| 945 | acpi_ut_get_object_type_name(return_object), | 1011 | acpi_ut_get_object_type_name |
| 946 | type_buffer)); | 1012 | (return_object), type_buffer)); |
| 947 | } | 1013 | } |
| 948 | 1014 | ||
| 949 | return (AE_AML_OPERAND_TYPE); | 1015 | return (AE_AML_OPERAND_TYPE); |
| @@ -953,7 +1019,7 @@ acpi_ns_check_object_type(char *pathname, | |||
| 953 | * | 1019 | * |
| 954 | * FUNCTION: acpi_ns_check_reference | 1020 | * FUNCTION: acpi_ns_check_reference |
| 955 | * | 1021 | * |
| 956 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | 1022 | * PARAMETERS: Data - Pointer to validation data structure |
| 957 | * return_object - Object returned from the evaluation of a | 1023 | * return_object - Object returned from the evaluation of a |
| 958 | * method or object | 1024 | * method or object |
| 959 | * | 1025 | * |
| @@ -966,7 +1032,7 @@ acpi_ns_check_object_type(char *pathname, | |||
| 966 | ******************************************************************************/ | 1032 | ******************************************************************************/ |
| 967 | 1033 | ||
| 968 | static acpi_status | 1034 | static acpi_status |
| 969 | acpi_ns_check_reference(char *pathname, | 1035 | acpi_ns_check_reference(struct acpi_predefined_data *data, |
| 970 | union acpi_operand_object *return_object) | 1036 | union acpi_operand_object *return_object) |
| 971 | { | 1037 | { |
| 972 | 1038 | ||
| @@ -979,94 +1045,46 @@ acpi_ns_check_reference(char *pathname, | |||
| 979 | return (AE_OK); | 1045 | return (AE_OK); |
| 980 | } | 1046 | } |
| 981 | 1047 | ||
| 982 | ACPI_WARNING((AE_INFO, | 1048 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, |
| 983 | "%s: Return type mismatch - " | 1049 | "Return type mismatch - unexpected reference object type [%s] %2.2X", |
| 984 | "unexpected reference object type [%s] %2.2X", | 1050 | acpi_ut_get_reference_name(return_object), |
| 985 | pathname, acpi_ut_get_reference_name(return_object), | 1051 | return_object->reference.class)); |
| 986 | return_object->reference.class)); | ||
| 987 | 1052 | ||
| 988 | return (AE_AML_OPERAND_TYPE); | 1053 | return (AE_AML_OPERAND_TYPE); |
| 989 | } | 1054 | } |
| 990 | 1055 | ||
| 991 | /******************************************************************************* | 1056 | /******************************************************************************* |
| 992 | * | 1057 | * |
| 993 | * FUNCTION: acpi_ns_repair_object | 1058 | * FUNCTION: acpi_ns_get_expected_types |
| 994 | * | 1059 | * |
| 995 | * PARAMETERS: Pathname - Full pathname to the node (for error msgs) | 1060 | * PARAMETERS: Buffer - Pointer to where the string is returned |
| 996 | * package_index - Used to determine if target is in a package | 1061 | * expected_btypes - Bitmap of expected return type(s) |
| 997 | * return_object_ptr - Pointer to the object returned from the | ||
| 998 | * evaluation of a method or object | ||
| 999 | * | 1062 | * |
| 1000 | * RETURN: Status. AE_OK if repair was successful. | 1063 | * RETURN: Buffer is populated with type names. |
| 1001 | * | 1064 | * |
| 1002 | * DESCRIPTION: Attempt to repair/convert a return object of a type that was | 1065 | * DESCRIPTION: Translate the expected types bitmap into a string of ascii |
| 1003 | * not expected. | 1066 | * names of expected types, for use in warning messages. |
| 1004 | * | 1067 | * |
| 1005 | ******************************************************************************/ | 1068 | ******************************************************************************/ |
| 1006 | 1069 | ||
| 1007 | static acpi_status | 1070 | static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes) |
| 1008 | acpi_ns_repair_object(u32 expected_btypes, | ||
| 1009 | u32 package_index, | ||
| 1010 | union acpi_operand_object **return_object_ptr) | ||
| 1011 | { | 1071 | { |
| 1012 | union acpi_operand_object *return_object = *return_object_ptr; | 1072 | u32 this_rtype; |
| 1013 | union acpi_operand_object *new_object; | 1073 | u32 i; |
| 1014 | acpi_size length; | 1074 | u32 j; |
| 1015 | |||
| 1016 | switch (return_object->common.type) { | ||
| 1017 | case ACPI_TYPE_BUFFER: | ||
| 1018 | |||
| 1019 | if (!(expected_btypes & ACPI_RTYPE_STRING)) { | ||
| 1020 | return (AE_AML_OPERAND_TYPE); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | /* | ||
| 1024 | * Have a Buffer, expected a String, convert. Use a to_string | ||
| 1025 | * conversion, no transform performed on the buffer data. The best | ||
| 1026 | * example of this is the _BIF method, where the string data from | ||
| 1027 | * the battery is often (incorrectly) returned as buffer object(s). | ||
| 1028 | */ | ||
| 1029 | length = 0; | ||
| 1030 | while ((length < return_object->buffer.length) && | ||
| 1031 | (return_object->buffer.pointer[length])) { | ||
| 1032 | length++; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /* Allocate a new string object */ | ||
| 1036 | |||
| 1037 | new_object = acpi_ut_create_string_object(length); | ||
| 1038 | if (!new_object) { | ||
| 1039 | return (AE_NO_MEMORY); | ||
| 1040 | } | ||
| 1041 | 1075 | ||
| 1042 | /* | 1076 | j = 1; |
| 1043 | * Copy the raw buffer data with no transform. String is already NULL | 1077 | buffer[0] = 0; |
| 1044 | * terminated at Length+1. | 1078 | this_rtype = ACPI_RTYPE_INTEGER; |
| 1045 | */ | ||
| 1046 | ACPI_MEMCPY(new_object->string.pointer, | ||
| 1047 | return_object->buffer.pointer, length); | ||
| 1048 | 1079 | ||
| 1049 | /* Install the new return object */ | 1080 | for (i = 0; i < ACPI_NUM_RTYPES; i++) { |
| 1050 | 1081 | ||
| 1051 | acpi_ut_remove_reference(return_object); | 1082 | /* If one of the expected types, concatenate the name of this type */ |
| 1052 | *return_object_ptr = new_object; | ||
| 1053 | 1083 | ||
| 1054 | /* | 1084 | if (expected_btypes & this_rtype) { |
| 1055 | * If the object is a package element, we need to: | 1085 | ACPI_STRCAT(buffer, &acpi_rtype_names[i][j]); |
| 1056 | * 1. Decrement the reference count of the orignal object, it was | 1086 | j = 0; /* Use name separator from now on */ |
| 1057 | * incremented when building the package | ||
| 1058 | * 2. Increment the reference count of the new object, it will be | ||
| 1059 | * decremented when releasing the package | ||
| 1060 | */ | ||
| 1061 | if (package_index != ACPI_NOT_PACKAGE) { | ||
| 1062 | acpi_ut_remove_reference(return_object); | ||
| 1063 | acpi_ut_add_reference(new_object); | ||
| 1064 | } | 1087 | } |
| 1065 | return (AE_OK); | 1088 | this_rtype <<= 1; /* Next Rtype */ |
| 1066 | |||
| 1067 | default: | ||
| 1068 | break; | ||
| 1069 | } | 1089 | } |
| 1070 | |||
| 1071 | return (AE_AML_OPERAND_TYPE); | ||
| 1072 | } | 1090 | } |
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c new file mode 100644 index 000000000000..db2b2a99c3a8 --- /dev/null +++ b/drivers/acpi/acpica/nsrepair.c | |||
| @@ -0,0 +1,203 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * Module Name: nsrepair - Repair for objects returned by predefined methods | ||
| 4 | * | ||
| 5 | *****************************************************************************/ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * Copyright (C) 2000 - 2009, Intel Corp. | ||
| 9 | * All rights reserved. | ||
| 10 | * | ||
| 11 | * Redistribution and use in source and binary forms, with or without | ||
| 12 | * modification, are permitted provided that the following conditions | ||
| 13 | * are met: | ||
| 14 | * 1. Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions, and the following disclaimer, | ||
| 16 | * without modification. | ||
| 17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
| 18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
| 19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
| 20 | * including a substantially similar Disclaimer requirement for further | ||
| 21 | * binary redistribution. | ||
| 22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
| 23 | * of any contributors may be used to endorse or promote products derived | ||
| 24 | * from this software without specific prior written permission. | ||
| 25 | * | ||
| 26 | * Alternatively, this software may be distributed under the terms of the | ||
| 27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
| 28 | * Software Foundation. | ||
| 29 | * | ||
| 30 | * NO WARRANTY | ||
| 31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
| 34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
| 40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 41 | * POSSIBILITY OF SUCH DAMAGES. | ||
| 42 | */ | ||
| 43 | |||
| 44 | #include <acpi/acpi.h> | ||
| 45 | #include "accommon.h" | ||
| 46 | #include "acnamesp.h" | ||
| 47 | #include "acpredef.h" | ||
| 48 | |||
| 49 | #define _COMPONENT ACPI_NAMESPACE | ||
| 50 | ACPI_MODULE_NAME("nsrepair") | ||
| 51 | |||
| 52 | /******************************************************************************* | ||
| 53 | * | ||
| 54 | * FUNCTION: acpi_ns_repair_object | ||
| 55 | * | ||
| 56 | * PARAMETERS: Data - Pointer to validation data structure | ||
| 57 | * expected_btypes - Object types expected | ||
| 58 | * package_index - Index of object within parent package (if | ||
| 59 | * applicable - ACPI_NOT_PACKAGE_ELEMENT | ||
| 60 | * otherwise) | ||
| 61 | * return_object_ptr - Pointer to the object returned from the | ||
| 62 | * evaluation of a method or object | ||
| 63 | * | ||
| 64 | * RETURN: Status. AE_OK if repair was successful. | ||
| 65 | * | ||
| 66 | * DESCRIPTION: Attempt to repair/convert a return object of a type that was | ||
| 67 | * not expected. | ||
| 68 | * | ||
| 69 | ******************************************************************************/ | ||
| 70 | acpi_status | ||
| 71 | acpi_ns_repair_object(struct acpi_predefined_data *data, | ||
| 72 | u32 expected_btypes, | ||
| 73 | u32 package_index, | ||
| 74 | union acpi_operand_object **return_object_ptr) | ||
| 75 | { | ||
| 76 | union acpi_operand_object *return_object = *return_object_ptr; | ||
| 77 | union acpi_operand_object *new_object; | ||
| 78 | acpi_size length; | ||
| 79 | |||
| 80 | switch (return_object->common.type) { | ||
| 81 | case ACPI_TYPE_BUFFER: | ||
| 82 | |||
| 83 | /* Does the method/object legally return a string? */ | ||
| 84 | |||
| 85 | if (!(expected_btypes & ACPI_RTYPE_STRING)) { | ||
| 86 | return (AE_AML_OPERAND_TYPE); | ||
| 87 | } | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Have a Buffer, expected a String, convert. Use a to_string | ||
| 91 | * conversion, no transform performed on the buffer data. The best | ||
| 92 | * example of this is the _BIF method, where the string data from | ||
| 93 | * the battery is often (incorrectly) returned as buffer object(s). | ||
| 94 | */ | ||
| 95 | length = 0; | ||
| 96 | while ((length < return_object->buffer.length) && | ||
| 97 | (return_object->buffer.pointer[length])) { | ||
| 98 | length++; | ||
| 99 | } | ||
| 100 | |||
| 101 | /* Allocate a new string object */ | ||
| 102 | |||
| 103 | new_object = acpi_ut_create_string_object(length); | ||
| 104 | if (!new_object) { | ||
| 105 | return (AE_NO_MEMORY); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* | ||
| 109 | * Copy the raw buffer data with no transform. String is already NULL | ||
| 110 | * terminated at Length+1. | ||
| 111 | */ | ||
| 112 | ACPI_MEMCPY(new_object->string.pointer, | ||
| 113 | return_object->buffer.pointer, length); | ||
| 114 | |||
| 115 | /* | ||
| 116 | * If the original object is a package element, we need to: | ||
| 117 | * 1. Set the reference count of the new object to match the | ||
| 118 | * reference count of the old object. | ||
| 119 | * 2. Decrement the reference count of the original object. | ||
| 120 | */ | ||
| 121 | if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { | ||
| 122 | new_object->common.reference_count = | ||
| 123 | return_object->common.reference_count; | ||
| 124 | |||
| 125 | if (return_object->common.reference_count > 1) { | ||
| 126 | return_object->common.reference_count--; | ||
| 127 | } | ||
| 128 | |||
| 129 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | ||
| 130 | data->node_flags, | ||
| 131 | "Converted Buffer to expected String at index %u", | ||
| 132 | package_index)); | ||
| 133 | } else { | ||
| 134 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | ||
| 135 | data->node_flags, | ||
| 136 | "Converted Buffer to expected String")); | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Delete old object, install the new return object */ | ||
| 140 | |||
| 141 | acpi_ut_remove_reference(return_object); | ||
| 142 | *return_object_ptr = new_object; | ||
| 143 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
| 144 | return (AE_OK); | ||
| 145 | |||
| 146 | default: | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | |||
| 150 | return (AE_AML_OPERAND_TYPE); | ||
| 151 | } | ||
| 152 | |||
| 153 | /******************************************************************************* | ||
| 154 | * | ||
| 155 | * FUNCTION: acpi_ns_repair_package_list | ||
| 156 | * | ||
| 157 | * PARAMETERS: Data - Pointer to validation data structure | ||
| 158 | * obj_desc_ptr - Pointer to the object to repair. The new | ||
| 159 | * package object is returned here, | ||
| 160 | * overwriting the old object. | ||
| 161 | * | ||
| 162 | * RETURN: Status, new object in *obj_desc_ptr | ||
| 163 | * | ||
| 164 | * DESCRIPTION: Repair a common problem with objects that are defined to return | ||
| 165 | * a variable-length Package of Packages. If the variable-length | ||
| 166 | * is one, some BIOS code mistakenly simply declares a single | ||
| 167 | * Package instead of a Package with one sub-Package. This | ||
| 168 | * function attempts to repair this error by wrapping a Package | ||
| 169 | * object around the original Package, creating the correct | ||
| 170 | * Package with one sub-Package. | ||
| 171 | * | ||
| 172 | * Names that can be repaired in this manner include: | ||
| 173 | * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS | ||
| 174 | * | ||
| 175 | ******************************************************************************/ | ||
| 176 | |||
| 177 | acpi_status | ||
| 178 | acpi_ns_repair_package_list(struct acpi_predefined_data *data, | ||
| 179 | union acpi_operand_object **obj_desc_ptr) | ||
| 180 | { | ||
| 181 | union acpi_operand_object *pkg_obj_desc; | ||
| 182 | |||
| 183 | /* | ||
| 184 | * Create the new outer package and populate it. The new package will | ||
| 185 | * have a single element, the lone subpackage. | ||
| 186 | */ | ||
| 187 | pkg_obj_desc = acpi_ut_create_package_object(1); | ||
| 188 | if (!pkg_obj_desc) { | ||
| 189 | return (AE_NO_MEMORY); | ||
| 190 | } | ||
| 191 | |||
| 192 | pkg_obj_desc->package.elements[0] = *obj_desc_ptr; | ||
| 193 | |||
| 194 | /* Return the new object in the object pointer */ | ||
| 195 | |||
| 196 | *obj_desc_ptr = pkg_obj_desc; | ||
| 197 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
| 198 | |||
| 199 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
| 200 | "Incorrectly formed Package, attempting repair")); | ||
| 201 | |||
| 202 | return (AE_OK); | ||
| 203 | } | ||
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 78277ed08339..ea55ab4f9849 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c | |||
| @@ -88,7 +88,8 @@ acpi_ns_report_error(const char *module_name, | |||
| 88 | 88 | ||
| 89 | /* There is a non-ascii character in the name */ | 89 | /* There is a non-ascii character in the name */ |
| 90 | 90 | ||
| 91 | ACPI_MOVE_32_TO_32(&bad_name, internal_name); | 91 | ACPI_MOVE_32_TO_32(&bad_name, |
| 92 | ACPI_CAST_PTR(u32, internal_name)); | ||
| 92 | acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); | 93 | acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); |
| 93 | } else { | 94 | } else { |
| 94 | /* Convert path to external format */ | 95 | /* Convert path to external format */ |
| @@ -836,7 +837,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, | |||
| 836 | acpi_status status; | 837 | acpi_status status; |
| 837 | char *internal_path; | 838 | char *internal_path; |
| 838 | 839 | ||
| 839 | ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); | 840 | ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); |
| 840 | 841 | ||
| 841 | if (!pathname) { | 842 | if (!pathname) { |
| 842 | *return_node = prefix_node; | 843 | *return_node = prefix_node; |
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index daf4ad37896d..4929dbdbc8f0 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c | |||
| @@ -535,10 +535,11 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, | |||
| 535 | acpi_status status; | 535 | acpi_status status; |
| 536 | struct acpi_namespace_node *node; | 536 | struct acpi_namespace_node *node; |
| 537 | u32 flags; | 537 | u32 flags; |
| 538 | struct acpica_device_id hid; | 538 | struct acpica_device_id *hid; |
| 539 | struct acpi_compatible_id_list *cid; | 539 | struct acpica_device_id_list *cid; |
| 540 | u32 i; | 540 | u32 i; |
| 541 | int found; | 541 | u8 found; |
| 542 | int no_match; | ||
| 542 | 543 | ||
| 543 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 544 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
| 544 | if (ACPI_FAILURE(status)) { | 545 | if (ACPI_FAILURE(status)) { |
| @@ -582,10 +583,14 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, | |||
| 582 | return (AE_CTRL_DEPTH); | 583 | return (AE_CTRL_DEPTH); |
| 583 | } | 584 | } |
| 584 | 585 | ||
| 585 | if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { | 586 | no_match = ACPI_STRCMP(hid->string, info->hid); |
| 586 | 587 | ACPI_FREE(hid); | |
| 587 | /* Get the list of Compatible IDs */ | ||
| 588 | 588 | ||
| 589 | if (no_match) { | ||
| 590 | /* | ||
| 591 | * HID does not match, attempt match within the | ||
| 592 | * list of Compatible IDs (CIDs) | ||
| 593 | */ | ||
| 589 | status = acpi_ut_execute_CID(node, &cid); | 594 | status = acpi_ut_execute_CID(node, &cid); |
| 590 | if (status == AE_NOT_FOUND) { | 595 | if (status == AE_NOT_FOUND) { |
| 591 | return (AE_OK); | 596 | return (AE_OK); |
| @@ -597,10 +602,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, | |||
| 597 | 602 | ||
| 598 | found = 0; | 603 | found = 0; |
| 599 | for (i = 0; i < cid->count; i++) { | 604 | for (i = 0; i < cid->count; i++) { |
| 600 | if (ACPI_STRNCMP(cid->id[i].value, info->hid, | 605 | if (ACPI_STRCMP(cid->ids[i].string, info->hid) |
| 601 | sizeof(struct | 606 | == 0) { |
| 602 | acpi_compatible_id)) == | ||
| 603 | 0) { | ||
| 604 | found = 1; | 607 | found = 1; |
| 605 | break; | 608 | break; |
| 606 | } | 609 | } |
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index f23593d6add4..ddc84af6336e 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c | |||
| @@ -51,6 +51,11 @@ | |||
| 51 | #define _COMPONENT ACPI_NAMESPACE | 51 | #define _COMPONENT ACPI_NAMESPACE |
| 52 | ACPI_MODULE_NAME("nsxfname") | 52 | ACPI_MODULE_NAME("nsxfname") |
| 53 | 53 | ||
| 54 | /* Local prototypes */ | ||
| 55 | static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, | ||
| 56 | struct acpica_device_id *source, | ||
| 57 | char *string_area); | ||
| 58 | |||
| 54 | /****************************************************************************** | 59 | /****************************************************************************** |
| 55 | * | 60 | * |
| 56 | * FUNCTION: acpi_get_handle | 61 | * FUNCTION: acpi_get_handle |
| @@ -68,6 +73,7 @@ ACPI_MODULE_NAME("nsxfname") | |||
| 68 | * namespace handle. | 73 | * namespace handle. |
| 69 | * | 74 | * |
| 70 | ******************************************************************************/ | 75 | ******************************************************************************/ |
| 76 | |||
| 71 | acpi_status | 77 | acpi_status |
| 72 | acpi_get_handle(acpi_handle parent, | 78 | acpi_get_handle(acpi_handle parent, |
| 73 | acpi_string pathname, acpi_handle * ret_handle) | 79 | acpi_string pathname, acpi_handle * ret_handle) |
| @@ -210,10 +216,38 @@ ACPI_EXPORT_SYMBOL(acpi_get_name) | |||
| 210 | 216 | ||
| 211 | /****************************************************************************** | 217 | /****************************************************************************** |
| 212 | * | 218 | * |
| 219 | * FUNCTION: acpi_ns_copy_device_id | ||
| 220 | * | ||
| 221 | * PARAMETERS: Dest - Pointer to the destination DEVICE_ID | ||
| 222 | * Source - Pointer to the source DEVICE_ID | ||
| 223 | * string_area - Pointer to where to copy the dest string | ||
| 224 | * | ||
| 225 | * RETURN: Pointer to the next string area | ||
| 226 | * | ||
| 227 | * DESCRIPTION: Copy a single DEVICE_ID, including the string data. | ||
| 228 | * | ||
| 229 | ******************************************************************************/ | ||
| 230 | static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, | ||
| 231 | struct acpica_device_id *source, | ||
| 232 | char *string_area) | ||
| 233 | { | ||
| 234 | /* Create the destination DEVICE_ID */ | ||
| 235 | |||
| 236 | dest->string = string_area; | ||
| 237 | dest->length = source->length; | ||
| 238 | |||
| 239 | /* Copy actual string and return a pointer to the next string area */ | ||
| 240 | |||
| 241 | ACPI_MEMCPY(string_area, source->string, source->length); | ||
| 242 | return (string_area + source->length); | ||
| 243 | } | ||
| 244 | |||
| 245 | /****************************************************************************** | ||
| 246 | * | ||
| 213 | * FUNCTION: acpi_get_object_info | 247 | * FUNCTION: acpi_get_object_info |
| 214 | * | 248 | * |
| 215 | * PARAMETERS: Handle - Object Handle | 249 | * PARAMETERS: Handle - Object Handle |
| 216 | * Buffer - Where the info is returned | 250 | * return_buffer - Where the info is returned |
| 217 | * | 251 | * |
| 218 | * RETURN: Status | 252 | * RETURN: Status |
| 219 | * | 253 | * |
| @@ -221,33 +255,37 @@ ACPI_EXPORT_SYMBOL(acpi_get_name) | |||
| 221 | * namespace node and possibly by running several standard | 255 | * namespace node and possibly by running several standard |
| 222 | * control methods (Such as in the case of a device.) | 256 | * control methods (Such as in the case of a device.) |
| 223 | * | 257 | * |
| 258 | * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, | ||
| 259 | * _ADR, _sx_w, and _sx_d methods. | ||
| 260 | * | ||
| 261 | * Note: Allocates the return buffer, must be freed by the caller. | ||
| 262 | * | ||
| 224 | ******************************************************************************/ | 263 | ******************************************************************************/ |
| 264 | |||
| 225 | acpi_status | 265 | acpi_status |
| 226 | acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | 266 | acpi_get_object_info(acpi_handle handle, |
| 267 | struct acpi_device_info **return_buffer) | ||
| 227 | { | 268 | { |
| 228 | acpi_status status; | ||
| 229 | struct acpi_namespace_node *node; | 269 | struct acpi_namespace_node *node; |
| 230 | struct acpi_device_info *info; | 270 | struct acpi_device_info *info; |
| 231 | struct acpi_device_info *return_info; | 271 | struct acpica_device_id_list *cid_list = NULL; |
| 232 | struct acpi_compatible_id_list *cid_list = NULL; | 272 | struct acpica_device_id *hid = NULL; |
| 233 | acpi_size size; | 273 | struct acpica_device_id *uid = NULL; |
| 274 | char *next_id_string; | ||
| 275 | acpi_object_type type; | ||
| 276 | acpi_name name; | ||
| 277 | u8 param_count = 0; | ||
| 278 | u8 valid = 0; | ||
| 279 | u32 info_size; | ||
| 280 | u32 i; | ||
| 281 | acpi_status status; | ||
| 234 | 282 | ||
| 235 | /* Parameter validation */ | 283 | /* Parameter validation */ |
| 236 | 284 | ||
| 237 | if (!handle || !buffer) { | 285 | if (!handle || !return_buffer) { |
| 238 | return (AE_BAD_PARAMETER); | 286 | return (AE_BAD_PARAMETER); |
| 239 | } | 287 | } |
| 240 | 288 | ||
| 241 | status = acpi_ut_validate_buffer(buffer); | ||
| 242 | if (ACPI_FAILURE(status)) { | ||
| 243 | return (status); | ||
| 244 | } | ||
| 245 | |||
| 246 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); | ||
| 247 | if (!info) { | ||
| 248 | return (AE_NO_MEMORY); | ||
| 249 | } | ||
| 250 | |||
| 251 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 289 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
| 252 | if (ACPI_FAILURE(status)) { | 290 | if (ACPI_FAILURE(status)) { |
| 253 | goto cleanup; | 291 | goto cleanup; |
| @@ -256,66 +294,91 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | |||
| 256 | node = acpi_ns_map_handle_to_node(handle); | 294 | node = acpi_ns_map_handle_to_node(handle); |
| 257 | if (!node) { | 295 | if (!node) { |
| 258 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 296 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
| 259 | status = AE_BAD_PARAMETER; | 297 | return (AE_BAD_PARAMETER); |
| 260 | goto cleanup; | ||
| 261 | } | 298 | } |
| 262 | 299 | ||
| 263 | /* Init return structure */ | 300 | /* Get the namespace node data while the namespace is locked */ |
| 264 | |||
| 265 | size = sizeof(struct acpi_device_info); | ||
| 266 | 301 | ||
| 267 | info->type = node->type; | 302 | info_size = sizeof(struct acpi_device_info); |
| 268 | info->name = node->name.integer; | 303 | type = node->type; |
| 269 | info->valid = 0; | 304 | name = node->name.integer; |
| 270 | 305 | ||
| 271 | if (node->type == ACPI_TYPE_METHOD) { | 306 | if (node->type == ACPI_TYPE_METHOD) { |
| 272 | info->param_count = node->object->method.param_count; | 307 | param_count = node->object->method.param_count; |
| 273 | } | 308 | } |
| 274 | 309 | ||
| 275 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 310 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
| 276 | if (ACPI_FAILURE(status)) { | 311 | if (ACPI_FAILURE(status)) { |
| 277 | goto cleanup; | 312 | return (status); |
| 278 | } | 313 | } |
| 279 | 314 | ||
| 280 | /* If not a device, we are all done */ | 315 | if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { |
| 281 | |||
| 282 | if (info->type == ACPI_TYPE_DEVICE) { | ||
| 283 | /* | 316 | /* |
| 284 | * Get extra info for ACPI Devices objects only: | 317 | * Get extra info for ACPI Device/Processor objects only: |
| 285 | * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. | 318 | * Run the Device _HID, _UID, and _CID methods. |
| 286 | * | 319 | * |
| 287 | * Note: none of these methods are required, so they may or may | 320 | * Note: none of these methods are required, so they may or may |
| 288 | * not be present for this device. The Info->Valid bitfield is used | 321 | * not be present for this device. The Info->Valid bitfield is used |
| 289 | * to indicate which methods were found and ran successfully. | 322 | * to indicate which methods were found and run successfully. |
| 290 | */ | 323 | */ |
| 291 | 324 | ||
| 292 | /* Execute the Device._HID method */ | 325 | /* Execute the Device._HID method */ |
| 293 | 326 | ||
| 294 | status = acpi_ut_execute_HID(node, &info->hardware_id); | 327 | status = acpi_ut_execute_HID(node, &hid); |
| 295 | if (ACPI_SUCCESS(status)) { | 328 | if (ACPI_SUCCESS(status)) { |
| 296 | info->valid |= ACPI_VALID_HID; | 329 | info_size += hid->length; |
| 330 | valid |= ACPI_VALID_HID; | ||
| 297 | } | 331 | } |
| 298 | 332 | ||
| 299 | /* Execute the Device._UID method */ | 333 | /* Execute the Device._UID method */ |
| 300 | 334 | ||
| 301 | status = acpi_ut_execute_UID(node, &info->unique_id); | 335 | status = acpi_ut_execute_UID(node, &uid); |
| 302 | if (ACPI_SUCCESS(status)) { | 336 | if (ACPI_SUCCESS(status)) { |
| 303 | info->valid |= ACPI_VALID_UID; | 337 | info_size += uid->length; |
| 338 | valid |= ACPI_VALID_UID; | ||
| 304 | } | 339 | } |
| 305 | 340 | ||
| 306 | /* Execute the Device._CID method */ | 341 | /* Execute the Device._CID method */ |
| 307 | 342 | ||
| 308 | status = acpi_ut_execute_CID(node, &cid_list); | 343 | status = acpi_ut_execute_CID(node, &cid_list); |
| 309 | if (ACPI_SUCCESS(status)) { | 344 | if (ACPI_SUCCESS(status)) { |
| 310 | size += cid_list->size; | 345 | |
| 311 | info->valid |= ACPI_VALID_CID; | 346 | /* Add size of CID strings and CID pointer array */ |
| 347 | |||
| 348 | info_size += | ||
| 349 | (cid_list->list_size - | ||
| 350 | sizeof(struct acpica_device_id_list)); | ||
| 351 | valid |= ACPI_VALID_CID; | ||
| 312 | } | 352 | } |
| 353 | } | ||
| 354 | |||
| 355 | /* | ||
| 356 | * Now that we have the variable-length data, we can allocate the | ||
| 357 | * return buffer | ||
| 358 | */ | ||
| 359 | info = ACPI_ALLOCATE_ZEROED(info_size); | ||
| 360 | if (!info) { | ||
| 361 | status = AE_NO_MEMORY; | ||
| 362 | goto cleanup; | ||
| 363 | } | ||
| 364 | |||
| 365 | /* Get the fixed-length data */ | ||
| 366 | |||
| 367 | if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { | ||
| 368 | /* | ||
| 369 | * Get extra info for ACPI Device/Processor objects only: | ||
| 370 | * Run the _STA, _ADR and, sx_w, and _sx_d methods. | ||
| 371 | * | ||
| 372 | * Note: none of these methods are required, so they may or may | ||
| 373 | * not be present for this device. The Info->Valid bitfield is used | ||
| 374 | * to indicate which methods were found and run successfully. | ||
| 375 | */ | ||
| 313 | 376 | ||
| 314 | /* Execute the Device._STA method */ | 377 | /* Execute the Device._STA method */ |
| 315 | 378 | ||
| 316 | status = acpi_ut_execute_STA(node, &info->current_status); | 379 | status = acpi_ut_execute_STA(node, &info->current_status); |
| 317 | if (ACPI_SUCCESS(status)) { | 380 | if (ACPI_SUCCESS(status)) { |
| 318 | info->valid |= ACPI_VALID_STA; | 381 | valid |= ACPI_VALID_STA; |
| 319 | } | 382 | } |
| 320 | 383 | ||
| 321 | /* Execute the Device._ADR method */ | 384 | /* Execute the Device._ADR method */ |
| @@ -323,36 +386,100 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | |||
| 323 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, | 386 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, |
| 324 | &info->address); | 387 | &info->address); |
| 325 | if (ACPI_SUCCESS(status)) { | 388 | if (ACPI_SUCCESS(status)) { |
| 326 | info->valid |= ACPI_VALID_ADR; | 389 | valid |= ACPI_VALID_ADR; |
| 390 | } | ||
| 391 | |||
| 392 | /* Execute the Device._sx_w methods */ | ||
| 393 | |||
| 394 | status = acpi_ut_execute_power_methods(node, | ||
| 395 | acpi_gbl_lowest_dstate_names, | ||
| 396 | ACPI_NUM_sx_w_METHODS, | ||
| 397 | info->lowest_dstates); | ||
| 398 | if (ACPI_SUCCESS(status)) { | ||
| 399 | valid |= ACPI_VALID_SXWS; | ||
| 327 | } | 400 | } |
| 328 | 401 | ||
| 329 | /* Execute the Device._sx_d methods */ | 402 | /* Execute the Device._sx_d methods */ |
| 330 | 403 | ||
| 331 | status = acpi_ut_execute_sxds(node, info->highest_dstates); | 404 | status = acpi_ut_execute_power_methods(node, |
| 405 | acpi_gbl_highest_dstate_names, | ||
| 406 | ACPI_NUM_sx_d_METHODS, | ||
| 407 | info->highest_dstates); | ||
| 332 | if (ACPI_SUCCESS(status)) { | 408 | if (ACPI_SUCCESS(status)) { |
| 333 | info->valid |= ACPI_VALID_SXDS; | 409 | valid |= ACPI_VALID_SXDS; |
| 334 | } | 410 | } |
| 335 | } | 411 | } |
| 336 | 412 | ||
| 337 | /* Validate/Allocate/Clear caller buffer */ | 413 | /* |
| 414 | * Create a pointer to the string area of the return buffer. | ||
| 415 | * Point to the end of the base struct acpi_device_info structure. | ||
| 416 | */ | ||
| 417 | next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); | ||
| 418 | if (cid_list) { | ||
| 338 | 419 | ||
| 339 | status = acpi_ut_initialize_buffer(buffer, size); | 420 | /* Point past the CID DEVICE_ID array */ |
| 340 | if (ACPI_FAILURE(status)) { | 421 | |
| 341 | goto cleanup; | 422 | next_id_string += |
| 423 | ((acpi_size) cid_list->count * | ||
| 424 | sizeof(struct acpica_device_id)); | ||
| 342 | } | 425 | } |
| 343 | 426 | ||
| 344 | /* Populate the return buffer */ | 427 | /* |
| 428 | * Copy the HID, UID, and CIDs to the return buffer. The variable-length | ||
| 429 | * strings are copied to the reserved area at the end of the buffer. | ||
| 430 | * | ||
| 431 | * For HID and CID, check if the ID is a PCI Root Bridge. | ||
| 432 | */ | ||
| 433 | if (hid) { | ||
| 434 | next_id_string = acpi_ns_copy_device_id(&info->hardware_id, | ||
| 435 | hid, next_id_string); | ||
| 436 | |||
| 437 | if (acpi_ut_is_pci_root_bridge(hid->string)) { | ||
| 438 | info->flags |= ACPI_PCI_ROOT_BRIDGE; | ||
| 439 | } | ||
| 440 | } | ||
| 345 | 441 | ||
| 346 | return_info = buffer->pointer; | 442 | if (uid) { |
| 347 | ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); | 443 | next_id_string = acpi_ns_copy_device_id(&info->unique_id, |
| 444 | uid, next_id_string); | ||
| 445 | } | ||
| 348 | 446 | ||
| 349 | if (cid_list) { | 447 | if (cid_list) { |
| 350 | ACPI_MEMCPY(&return_info->compatibility_id, cid_list, | 448 | info->compatible_id_list.count = cid_list->count; |
| 351 | cid_list->size); | 449 | info->compatible_id_list.list_size = cid_list->list_size; |
| 450 | |||
| 451 | /* Copy each CID */ | ||
| 452 | |||
| 453 | for (i = 0; i < cid_list->count; i++) { | ||
| 454 | next_id_string = | ||
| 455 | acpi_ns_copy_device_id(&info->compatible_id_list. | ||
| 456 | ids[i], &cid_list->ids[i], | ||
| 457 | next_id_string); | ||
| 458 | |||
| 459 | if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) { | ||
| 460 | info->flags |= ACPI_PCI_ROOT_BRIDGE; | ||
| 461 | } | ||
| 462 | } | ||
| 352 | } | 463 | } |
| 353 | 464 | ||
| 465 | /* Copy the fixed-length data */ | ||
| 466 | |||
| 467 | info->info_size = info_size; | ||
| 468 | info->type = type; | ||
| 469 | info->name = name; | ||
| 470 | info->param_count = param_count; | ||
| 471 | info->valid = valid; | ||
| 472 | |||
| 473 | *return_buffer = info; | ||
| 474 | status = AE_OK; | ||
| 475 | |||
| 354 | cleanup: | 476 | cleanup: |
| 355 | ACPI_FREE(info); | 477 | if (hid) { |
| 478 | ACPI_FREE(hid); | ||
| 479 | } | ||
| 480 | if (uid) { | ||
| 481 | ACPI_FREE(uid); | ||
| 482 | } | ||
| 356 | if (cid_list) { | 483 | if (cid_list) { |
| 357 | ACPI_FREE(cid_list); | 484 | ACPI_FREE(cid_list); |
| 358 | } | 485 | } |
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index c5f6ce19a401..cd7995b3aed4 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c | |||
| @@ -86,6 +86,9 @@ static acpi_status | |||
| 86 | acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, | 86 | acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, |
| 87 | union acpi_parse_object *op, acpi_status status); | 87 | union acpi_parse_object *op, acpi_status status); |
| 88 | 88 | ||
| 89 | static void | ||
| 90 | acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); | ||
| 91 | |||
| 89 | /******************************************************************************* | 92 | /******************************************************************************* |
| 90 | * | 93 | * |
| 91 | * FUNCTION: acpi_ps_get_aml_opcode | 94 | * FUNCTION: acpi_ps_get_aml_opcode |
| @@ -390,6 +393,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
| 390 | { | 393 | { |
| 391 | acpi_status status = AE_OK; | 394 | acpi_status status = AE_OK; |
| 392 | union acpi_parse_object *arg = NULL; | 395 | union acpi_parse_object *arg = NULL; |
| 396 | const struct acpi_opcode_info *op_info; | ||
| 393 | 397 | ||
| 394 | ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); | 398 | ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); |
| 395 | 399 | ||
| @@ -449,13 +453,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
| 449 | INCREMENT_ARG_LIST(walk_state->arg_types); | 453 | INCREMENT_ARG_LIST(walk_state->arg_types); |
| 450 | } | 454 | } |
| 451 | 455 | ||
| 452 | /* Special processing for certain opcodes */ | 456 | /* |
| 453 | 457 | * Handle executable code at "module-level". This refers to | |
| 454 | /* TBD (remove): Temporary mechanism to disable this code if needed */ | 458 | * executable opcodes that appear outside of any control method. |
| 455 | 459 | */ | |
| 456 | #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE | 460 | if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) && |
| 457 | |||
| 458 | if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && | ||
| 459 | ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { | 461 | ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { |
| 460 | /* | 462 | /* |
| 461 | * We want to skip If/Else/While constructs during Pass1 because we | 463 | * We want to skip If/Else/While constructs during Pass1 because we |
| @@ -469,6 +471,23 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
| 469 | case AML_ELSE_OP: | 471 | case AML_ELSE_OP: |
| 470 | case AML_WHILE_OP: | 472 | case AML_WHILE_OP: |
| 471 | 473 | ||
| 474 | /* | ||
| 475 | * Currently supported module-level opcodes are: | ||
| 476 | * IF/ELSE/WHILE. These appear to be the most common, | ||
| 477 | * and easiest to support since they open an AML | ||
| 478 | * package. | ||
| 479 | */ | ||
| 480 | if (walk_state->pass_number == | ||
| 481 | ACPI_IMODE_LOAD_PASS1) { | ||
| 482 | acpi_ps_link_module_code(aml_op_start, | ||
| 483 | walk_state-> | ||
| 484 | parser_state. | ||
| 485 | pkg_end - | ||
| 486 | aml_op_start, | ||
| 487 | walk_state-> | ||
| 488 | owner_id); | ||
| 489 | } | ||
| 490 | |||
| 472 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, | 491 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
| 473 | "Pass1: Skipping an If/Else/While body\n")); | 492 | "Pass1: Skipping an If/Else/While body\n")); |
| 474 | 493 | ||
| @@ -480,10 +499,34 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
| 480 | break; | 499 | break; |
| 481 | 500 | ||
| 482 | default: | 501 | default: |
| 502 | /* | ||
| 503 | * Check for an unsupported executable opcode at module | ||
| 504 | * level. We must be in PASS1, the parent must be a SCOPE, | ||
| 505 | * The opcode class must be EXECUTE, and the opcode must | ||
| 506 | * not be an argument to another opcode. | ||
| 507 | */ | ||
| 508 | if ((walk_state->pass_number == | ||
| 509 | ACPI_IMODE_LOAD_PASS1) | ||
| 510 | && (op->common.parent->common.aml_opcode == | ||
| 511 | AML_SCOPE_OP)) { | ||
| 512 | op_info = | ||
| 513 | acpi_ps_get_opcode_info(op->common. | ||
| 514 | aml_opcode); | ||
| 515 | if ((op_info->class == | ||
| 516 | AML_CLASS_EXECUTE) && (!arg)) { | ||
| 517 | ACPI_WARNING((AE_INFO, | ||
| 518 | "Detected an unsupported executable opcode " | ||
| 519 | "at module-level: [0x%.4X] at table offset 0x%.4X", | ||
| 520 | op->common.aml_opcode, | ||
| 521 | (u32)((aml_op_start - walk_state->parser_state.aml_start) | ||
| 522 | + sizeof(struct acpi_table_header)))); | ||
| 523 | } | ||
| 524 | } | ||
| 483 | break; | 525 | break; |
| 484 | } | 526 | } |
| 485 | } | 527 | } |
| 486 | #endif | 528 | |
| 529 | /* Special processing for certain opcodes */ | ||
| 487 | 530 | ||
| 488 | switch (op->common.aml_opcode) { | 531 | switch (op->common.aml_opcode) { |
| 489 | case AML_METHOD_OP: | 532 | case AML_METHOD_OP: |
| @@ -553,6 +596,66 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
| 553 | 596 | ||
| 554 | /******************************************************************************* | 597 | /******************************************************************************* |
| 555 | * | 598 | * |
| 599 | * FUNCTION: acpi_ps_link_module_code | ||
| 600 | * | ||
| 601 | * PARAMETERS: aml_start - Pointer to the AML | ||
| 602 | * aml_length - Length of executable AML | ||
| 603 | * owner_id - owner_id of module level code | ||
| 604 | * | ||
| 605 | * RETURN: None. | ||
| 606 | * | ||
| 607 | * DESCRIPTION: Wrap the module-level code with a method object and link the | ||
| 608 | * object to the global list. Note, the mutex field of the method | ||
| 609 | * object is used to link multiple module-level code objects. | ||
| 610 | * | ||
| 611 | ******************************************************************************/ | ||
| 612 | |||
| 613 | static void | ||
| 614 | acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) | ||
| 615 | { | ||
| 616 | union acpi_operand_object *prev; | ||
| 617 | union acpi_operand_object *next; | ||
| 618 | union acpi_operand_object *method_obj; | ||
| 619 | |||
| 620 | /* Get the tail of the list */ | ||
| 621 | |||
| 622 | prev = next = acpi_gbl_module_code_list; | ||
| 623 | while (next) { | ||
| 624 | prev = next; | ||
| 625 | next = next->method.mutex; | ||
| 626 | } | ||
| 627 | |||
| 628 | /* | ||
| 629 | * Insert the module level code into the list. Merge it if it is | ||
| 630 | * adjacent to the previous element. | ||
| 631 | */ | ||
| 632 | if (!prev || | ||
| 633 | ((prev->method.aml_start + prev->method.aml_length) != aml_start)) { | ||
| 634 | |||
| 635 | /* Create, initialize, and link a new temporary method object */ | ||
| 636 | |||
| 637 | method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); | ||
| 638 | if (!method_obj) { | ||
| 639 | return; | ||
| 640 | } | ||
| 641 | |||
| 642 | method_obj->method.aml_start = aml_start; | ||
| 643 | method_obj->method.aml_length = aml_length; | ||
| 644 | method_obj->method.owner_id = owner_id; | ||
| 645 | method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; | ||
| 646 | |||
| 647 | if (!prev) { | ||
| 648 | acpi_gbl_module_code_list = method_obj; | ||
| 649 | } else { | ||
| 650 | prev->method.mutex = method_obj; | ||
| 651 | } | ||
| 652 | } else { | ||
| 653 | prev->method.aml_length += aml_length; | ||
| 654 | } | ||
| 655 | } | ||
| 656 | |||
| 657 | /******************************************************************************* | ||
| 658 | * | ||
| 556 | * FUNCTION: acpi_ps_complete_op | 659 | * FUNCTION: acpi_ps_complete_op |
| 557 | * | 660 | * |
| 558 | * PARAMETERS: walk_state - Current state | 661 | * PARAMETERS: walk_state - Current state |
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index ff06032c0f06..dd9731c29a79 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c | |||
| @@ -280,6 +280,10 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) | |||
| 280 | goto cleanup; | 280 | goto cleanup; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) { | ||
| 284 | walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL; | ||
| 285 | } | ||
| 286 | |||
| 283 | /* Invoke an internal method if necessary */ | 287 | /* Invoke an internal method if necessary */ |
| 284 | 288 | ||
| 285 | if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | 289 | if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { |
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index ef7d2c2d8f0b..1f15497f00d1 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
| @@ -49,6 +49,12 @@ | |||
| 49 | ACPI_MODULE_NAME("tbutils") | 49 | ACPI_MODULE_NAME("tbutils") |
| 50 | 50 | ||
| 51 | /* Local prototypes */ | 51 | /* Local prototypes */ |
| 52 | static void acpi_tb_fix_string(char *string, acpi_size length); | ||
| 53 | |||
| 54 | static void | ||
| 55 | acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, | ||
| 56 | struct acpi_table_header *header); | ||
| 57 | |||
| 52 | static acpi_physical_address | 58 | static acpi_physical_address |
| 53 | acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); | 59 | acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); |
| 54 | 60 | ||
| @@ -161,6 +167,59 @@ u8 acpi_tb_tables_loaded(void) | |||
| 161 | 167 | ||
| 162 | /******************************************************************************* | 168 | /******************************************************************************* |
| 163 | * | 169 | * |
| 170 | * FUNCTION: acpi_tb_fix_string | ||
| 171 | * | ||
| 172 | * PARAMETERS: String - String to be repaired | ||
| 173 | * Length - Maximum length | ||
| 174 | * | ||
| 175 | * RETURN: None | ||
| 176 | * | ||
| 177 | * DESCRIPTION: Replace every non-printable or non-ascii byte in the string | ||
| 178 | * with a question mark '?'. | ||
| 179 | * | ||
| 180 | ******************************************************************************/ | ||
| 181 | |||
| 182 | static void acpi_tb_fix_string(char *string, acpi_size length) | ||
| 183 | { | ||
| 184 | |||
| 185 | while (length && *string) { | ||
| 186 | if (!ACPI_IS_PRINT(*string)) { | ||
| 187 | *string = '?'; | ||
| 188 | } | ||
| 189 | string++; | ||
| 190 | length--; | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | /******************************************************************************* | ||
| 195 | * | ||
| 196 | * FUNCTION: acpi_tb_cleanup_table_header | ||
| 197 | * | ||
| 198 | * PARAMETERS: out_header - Where the cleaned header is returned | ||
| 199 | * Header - Input ACPI table header | ||
| 200 | * | ||
| 201 | * RETURN: Returns the cleaned header in out_header | ||
| 202 | * | ||
| 203 | * DESCRIPTION: Copy the table header and ensure that all "string" fields in | ||
| 204 | * the header consist of printable characters. | ||
| 205 | * | ||
| 206 | ******************************************************************************/ | ||
| 207 | |||
| 208 | static void | ||
| 209 | acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, | ||
| 210 | struct acpi_table_header *header) | ||
| 211 | { | ||
| 212 | |||
| 213 | ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); | ||
| 214 | |||
| 215 | acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); | ||
| 216 | acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); | ||
| 217 | acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); | ||
| 218 | acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); | ||
| 219 | } | ||
| 220 | |||
| 221 | /******************************************************************************* | ||
| 222 | * | ||
| 164 | * FUNCTION: acpi_tb_print_table_header | 223 | * FUNCTION: acpi_tb_print_table_header |
| 165 | * | 224 | * |
| 166 | * PARAMETERS: Address - Table physical address | 225 | * PARAMETERS: Address - Table physical address |
| @@ -176,6 +235,7 @@ void | |||
| 176 | acpi_tb_print_table_header(acpi_physical_address address, | 235 | acpi_tb_print_table_header(acpi_physical_address address, |
| 177 | struct acpi_table_header *header) | 236 | struct acpi_table_header *header) |
| 178 | { | 237 | { |
| 238 | struct acpi_table_header local_header; | ||
| 179 | 239 | ||
| 180 | /* | 240 | /* |
| 181 | * The reason that the Address is cast to a void pointer is so that we | 241 | * The reason that the Address is cast to a void pointer is so that we |
| @@ -192,6 +252,11 @@ acpi_tb_print_table_header(acpi_physical_address address, | |||
| 192 | 252 | ||
| 193 | /* RSDP has no common fields */ | 253 | /* RSDP has no common fields */ |
| 194 | 254 | ||
| 255 | ACPI_MEMCPY(local_header.oem_id, | ||
| 256 | ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
| 257 | header)->oem_id, ACPI_OEM_ID_SIZE); | ||
| 258 | acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); | ||
| 259 | |||
| 195 | ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", | 260 | ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", |
| 196 | ACPI_CAST_PTR (void, address), | 261 | ACPI_CAST_PTR (void, address), |
| 197 | (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> | 262 | (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> |
| @@ -200,18 +265,21 @@ acpi_tb_print_table_header(acpi_physical_address address, | |||
| 200 | header)->length : 20, | 265 | header)->length : 20, |
| 201 | ACPI_CAST_PTR(struct acpi_table_rsdp, | 266 | ACPI_CAST_PTR(struct acpi_table_rsdp, |
| 202 | header)->revision, | 267 | header)->revision, |
| 203 | ACPI_CAST_PTR(struct acpi_table_rsdp, | 268 | local_header.oem_id)); |
| 204 | header)->oem_id)); | ||
| 205 | } else { | 269 | } else { |
| 206 | /* Standard ACPI table with full common header */ | 270 | /* Standard ACPI table with full common header */ |
| 207 | 271 | ||
| 272 | acpi_tb_cleanup_table_header(&local_header, header); | ||
| 273 | |||
| 208 | ACPI_INFO((AE_INFO, | 274 | ACPI_INFO((AE_INFO, |
| 209 | "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", | 275 | "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", |
| 210 | header->signature, ACPI_CAST_PTR (void, address), | 276 | local_header.signature, ACPI_CAST_PTR(void, address), |
| 211 | header->length, header->revision, header->oem_id, | 277 | local_header.length, local_header.revision, |
| 212 | header->oem_table_id, header->oem_revision, | 278 | local_header.oem_id, local_header.oem_table_id, |
| 213 | header->asl_compiler_id, | 279 | local_header.oem_revision, |
| 214 | header->asl_compiler_revision)); | 280 | local_header.asl_compiler_id, |
| 281 | local_header.asl_compiler_revision)); | ||
| 282 | |||
| 215 | } | 283 | } |
| 216 | } | 284 | } |
| 217 | 285 | ||
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index bc1710315088..96e26e70c63d 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c | |||
| @@ -215,6 +215,12 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) | |||
| 215 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, | 215 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, |
| 216 | "***** Region %p\n", object)); | 216 | "***** Region %p\n", object)); |
| 217 | 217 | ||
| 218 | /* Invalidate the region address/length via the host OS */ | ||
| 219 | |||
| 220 | acpi_os_invalidate_address(object->region.space_id, | ||
| 221 | object->region.address, | ||
| 222 | (acpi_size) object->region.length); | ||
| 223 | |||
| 218 | second_desc = acpi_ns_get_secondary_object(object); | 224 | second_desc = acpi_ns_get_secondary_object(object); |
| 219 | if (second_desc) { | 225 | if (second_desc) { |
| 220 | /* | 226 | /* |
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 006b16c26017..5d54e36ab453 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c | |||
| @@ -44,19 +44,10 @@ | |||
| 44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
| 45 | #include "accommon.h" | 45 | #include "accommon.h" |
| 46 | #include "acnamesp.h" | 46 | #include "acnamesp.h" |
| 47 | #include "acinterp.h" | ||
| 48 | 47 | ||
| 49 | #define _COMPONENT ACPI_UTILITIES | 48 | #define _COMPONENT ACPI_UTILITIES |
| 50 | ACPI_MODULE_NAME("uteval") | 49 | ACPI_MODULE_NAME("uteval") |
| 51 | 50 | ||
| 52 | /* Local prototypes */ | ||
| 53 | static void | ||
| 54 | acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length); | ||
| 55 | |||
| 56 | static acpi_status | ||
| 57 | acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, | ||
| 58 | struct acpi_compatible_id *one_cid); | ||
| 59 | |||
| 60 | /* | 51 | /* |
| 61 | * Strings supported by the _OSI predefined (internal) method. | 52 | * Strings supported by the _OSI predefined (internal) method. |
| 62 | * | 53 | * |
| @@ -78,6 +69,9 @@ static struct acpi_interface_info acpi_interfaces_supported[] = { | |||
| 78 | {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ | 69 | {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ |
| 79 | {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ | 70 | {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ |
| 80 | {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ | 71 | {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ |
| 72 | {"Windows 2006.1", ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ | ||
| 73 | {"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ | ||
| 74 | {"Windows 2009", ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ | ||
| 81 | 75 | ||
| 82 | /* Feature Group Strings */ | 76 | /* Feature Group Strings */ |
| 83 | 77 | ||
| @@ -213,7 +207,7 @@ acpi_status acpi_osi_invalidate(char *interface) | |||
| 213 | * RETURN: Status | 207 | * RETURN: Status |
| 214 | * | 208 | * |
| 215 | * DESCRIPTION: Evaluates a namespace object and verifies the type of the | 209 | * DESCRIPTION: Evaluates a namespace object and verifies the type of the |
| 216 | * return object. Common code that simplifies accessing objects | 210 | * return object. Common code that simplifies accessing objects |
| 217 | * that have required return objects of fixed types. | 211 | * that have required return objects of fixed types. |
| 218 | * | 212 | * |
| 219 | * NOTE: Internal function, no parameter validation | 213 | * NOTE: Internal function, no parameter validation |
| @@ -298,7 +292,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
| 298 | 292 | ||
| 299 | if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { | 293 | if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { |
| 300 | /* | 294 | /* |
| 301 | * We received a return object, but one was not expected. This can | 295 | * We received a return object, but one was not expected. This can |
| 302 | * happen frequently if the "implicit return" feature is enabled. | 296 | * happen frequently if the "implicit return" feature is enabled. |
| 303 | * Just delete the return object and return AE_OK. | 297 | * Just delete the return object and return AE_OK. |
| 304 | */ | 298 | */ |
| @@ -340,12 +334,12 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
| 340 | * | 334 | * |
| 341 | * PARAMETERS: object_name - Object name to be evaluated | 335 | * PARAMETERS: object_name - Object name to be evaluated |
| 342 | * device_node - Node for the device | 336 | * device_node - Node for the device |
| 343 | * Address - Where the value is returned | 337 | * Value - Where the value is returned |
| 344 | * | 338 | * |
| 345 | * RETURN: Status | 339 | * RETURN: Status |
| 346 | * | 340 | * |
| 347 | * DESCRIPTION: Evaluates a numeric namespace object for a selected device | 341 | * DESCRIPTION: Evaluates a numeric namespace object for a selected device |
| 348 | * and stores result in *Address. | 342 | * and stores result in *Value. |
| 349 | * | 343 | * |
| 350 | * NOTE: Internal function, no parameter validation | 344 | * NOTE: Internal function, no parameter validation |
| 351 | * | 345 | * |
| @@ -354,7 +348,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
| 354 | acpi_status | 348 | acpi_status |
| 355 | acpi_ut_evaluate_numeric_object(char *object_name, | 349 | acpi_ut_evaluate_numeric_object(char *object_name, |
| 356 | struct acpi_namespace_node *device_node, | 350 | struct acpi_namespace_node *device_node, |
| 357 | acpi_integer * address) | 351 | acpi_integer *value) |
| 358 | { | 352 | { |
| 359 | union acpi_operand_object *obj_desc; | 353 | union acpi_operand_object *obj_desc; |
| 360 | acpi_status status; | 354 | acpi_status status; |
| @@ -369,295 +363,7 @@ acpi_ut_evaluate_numeric_object(char *object_name, | |||
| 369 | 363 | ||
| 370 | /* Get the returned Integer */ | 364 | /* Get the returned Integer */ |
| 371 | 365 | ||
| 372 | *address = obj_desc->integer.value; | 366 | *value = obj_desc->integer.value; |
| 373 | |||
| 374 | /* On exit, we must delete the return object */ | ||
| 375 | |||
| 376 | acpi_ut_remove_reference(obj_desc); | ||
| 377 | return_ACPI_STATUS(status); | ||
| 378 | } | ||
| 379 | |||
| 380 | /******************************************************************************* | ||
| 381 | * | ||
| 382 | * FUNCTION: acpi_ut_copy_id_string | ||
| 383 | * | ||
| 384 | * PARAMETERS: Destination - Where to copy the string | ||
| 385 | * Source - Source string | ||
| 386 | * max_length - Length of the destination buffer | ||
| 387 | * | ||
| 388 | * RETURN: None | ||
| 389 | * | ||
| 390 | * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. | ||
| 391 | * Performs removal of a leading asterisk if present -- workaround | ||
| 392 | * for a known issue on a bunch of machines. | ||
| 393 | * | ||
| 394 | ******************************************************************************/ | ||
| 395 | |||
| 396 | static void | ||
| 397 | acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length) | ||
| 398 | { | ||
| 399 | |||
| 400 | /* | ||
| 401 | * Workaround for ID strings that have a leading asterisk. This construct | ||
| 402 | * is not allowed by the ACPI specification (ID strings must be | ||
| 403 | * alphanumeric), but enough existing machines have this embedded in their | ||
| 404 | * ID strings that the following code is useful. | ||
| 405 | */ | ||
| 406 | if (*source == '*') { | ||
| 407 | source++; | ||
| 408 | } | ||
| 409 | |||
| 410 | /* Do the actual copy */ | ||
| 411 | |||
| 412 | ACPI_STRNCPY(destination, source, max_length); | ||
| 413 | } | ||
| 414 | |||
| 415 | /******************************************************************************* | ||
| 416 | * | ||
| 417 | * FUNCTION: acpi_ut_execute_HID | ||
| 418 | * | ||
| 419 | * PARAMETERS: device_node - Node for the device | ||
| 420 | * Hid - Where the HID is returned | ||
| 421 | * | ||
| 422 | * RETURN: Status | ||
| 423 | * | ||
| 424 | * DESCRIPTION: Executes the _HID control method that returns the hardware | ||
| 425 | * ID of the device. | ||
| 426 | * | ||
| 427 | * NOTE: Internal function, no parameter validation | ||
| 428 | * | ||
| 429 | ******************************************************************************/ | ||
| 430 | |||
| 431 | acpi_status | ||
| 432 | acpi_ut_execute_HID(struct acpi_namespace_node *device_node, | ||
| 433 | struct acpica_device_id *hid) | ||
| 434 | { | ||
| 435 | union acpi_operand_object *obj_desc; | ||
| 436 | acpi_status status; | ||
| 437 | |||
| 438 | ACPI_FUNCTION_TRACE(ut_execute_HID); | ||
| 439 | |||
| 440 | status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, | ||
| 441 | ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, | ||
| 442 | &obj_desc); | ||
| 443 | if (ACPI_FAILURE(status)) { | ||
| 444 | return_ACPI_STATUS(status); | ||
| 445 | } | ||
| 446 | |||
| 447 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | ||
| 448 | |||
| 449 | /* Convert the Numeric HID to string */ | ||
| 450 | |||
| 451 | acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, | ||
| 452 | hid->value); | ||
| 453 | } else { | ||
| 454 | /* Copy the String HID from the returned object */ | ||
| 455 | |||
| 456 | acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer, | ||
| 457 | sizeof(hid->value)); | ||
| 458 | } | ||
| 459 | |||
| 460 | /* On exit, we must delete the return object */ | ||
| 461 | |||
| 462 | acpi_ut_remove_reference(obj_desc); | ||
| 463 | return_ACPI_STATUS(status); | ||
| 464 | } | ||
| 465 | |||
| 466 | /******************************************************************************* | ||
| 467 | * | ||
| 468 | * FUNCTION: acpi_ut_translate_one_cid | ||
| 469 | * | ||
| 470 | * PARAMETERS: obj_desc - _CID object, must be integer or string | ||
| 471 | * one_cid - Where the CID string is returned | ||
| 472 | * | ||
| 473 | * RETURN: Status | ||
| 474 | * | ||
| 475 | * DESCRIPTION: Return a numeric or string _CID value as a string. | ||
| 476 | * (Compatible ID) | ||
| 477 | * | ||
| 478 | * NOTE: Assumes a maximum _CID string length of | ||
| 479 | * ACPI_MAX_CID_LENGTH. | ||
| 480 | * | ||
| 481 | ******************************************************************************/ | ||
| 482 | |||
| 483 | static acpi_status | ||
| 484 | acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, | ||
| 485 | struct acpi_compatible_id *one_cid) | ||
| 486 | { | ||
| 487 | |||
| 488 | switch (obj_desc->common.type) { | ||
| 489 | case ACPI_TYPE_INTEGER: | ||
| 490 | |||
| 491 | /* Convert the Numeric CID to string */ | ||
| 492 | |||
| 493 | acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, | ||
| 494 | one_cid->value); | ||
| 495 | return (AE_OK); | ||
| 496 | |||
| 497 | case ACPI_TYPE_STRING: | ||
| 498 | |||
| 499 | if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { | ||
| 500 | return (AE_AML_STRING_LIMIT); | ||
| 501 | } | ||
| 502 | |||
| 503 | /* Copy the String CID from the returned object */ | ||
| 504 | |||
| 505 | acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer, | ||
| 506 | ACPI_MAX_CID_LENGTH); | ||
| 507 | return (AE_OK); | ||
| 508 | |||
| 509 | default: | ||
| 510 | |||
| 511 | return (AE_TYPE); | ||
| 512 | } | ||
| 513 | } | ||
| 514 | |||
| 515 | /******************************************************************************* | ||
| 516 | * | ||
| 517 | * FUNCTION: acpi_ut_execute_CID | ||
| 518 | * | ||
| 519 | * PARAMETERS: device_node - Node for the device | ||
| 520 | * return_cid_list - Where the CID list is returned | ||
| 521 | * | ||
| 522 | * RETURN: Status | ||
| 523 | * | ||
| 524 | * DESCRIPTION: Executes the _CID control method that returns one or more | ||
| 525 | * compatible hardware IDs for the device. | ||
| 526 | * | ||
| 527 | * NOTE: Internal function, no parameter validation | ||
| 528 | * | ||
| 529 | ******************************************************************************/ | ||
| 530 | |||
| 531 | acpi_status | ||
| 532 | acpi_ut_execute_CID(struct acpi_namespace_node * device_node, | ||
| 533 | struct acpi_compatible_id_list ** return_cid_list) | ||
| 534 | { | ||
| 535 | union acpi_operand_object *obj_desc; | ||
| 536 | acpi_status status; | ||
| 537 | u32 count; | ||
| 538 | u32 size; | ||
| 539 | struct acpi_compatible_id_list *cid_list; | ||
| 540 | u32 i; | ||
| 541 | |||
| 542 | ACPI_FUNCTION_TRACE(ut_execute_CID); | ||
| 543 | |||
| 544 | /* Evaluate the _CID method for this device */ | ||
| 545 | |||
| 546 | status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, | ||
| 547 | ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ||
| 548 | | ACPI_BTYPE_PACKAGE, &obj_desc); | ||
| 549 | if (ACPI_FAILURE(status)) { | ||
| 550 | return_ACPI_STATUS(status); | ||
| 551 | } | ||
| 552 | |||
| 553 | /* Get the number of _CIDs returned */ | ||
| 554 | |||
| 555 | count = 1; | ||
| 556 | if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { | ||
| 557 | count = obj_desc->package.count; | ||
| 558 | } | ||
| 559 | |||
| 560 | /* Allocate a worst-case buffer for the _CIDs */ | ||
| 561 | |||
| 562 | size = (((count - 1) * sizeof(struct acpi_compatible_id)) + | ||
| 563 | sizeof(struct acpi_compatible_id_list)); | ||
| 564 | |||
| 565 | cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); | ||
| 566 | if (!cid_list) { | ||
| 567 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
| 568 | } | ||
| 569 | |||
| 570 | /* Init CID list */ | ||
| 571 | |||
| 572 | cid_list->count = count; | ||
| 573 | cid_list->size = size; | ||
| 574 | |||
| 575 | /* | ||
| 576 | * A _CID can return either a single compatible ID or a package of | ||
| 577 | * compatible IDs. Each compatible ID can be one of the following: | ||
| 578 | * 1) Integer (32 bit compressed EISA ID) or | ||
| 579 | * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") | ||
| 580 | */ | ||
| 581 | |||
| 582 | /* The _CID object can be either a single CID or a package (list) of CIDs */ | ||
| 583 | |||
| 584 | if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { | ||
| 585 | |||
| 586 | /* Translate each package element */ | ||
| 587 | |||
| 588 | for (i = 0; i < count; i++) { | ||
| 589 | status = | ||
| 590 | acpi_ut_translate_one_cid(obj_desc->package. | ||
| 591 | elements[i], | ||
| 592 | &cid_list->id[i]); | ||
| 593 | if (ACPI_FAILURE(status)) { | ||
| 594 | break; | ||
| 595 | } | ||
| 596 | } | ||
| 597 | } else { | ||
| 598 | /* Only one CID, translate to a string */ | ||
| 599 | |||
| 600 | status = acpi_ut_translate_one_cid(obj_desc, cid_list->id); | ||
| 601 | } | ||
| 602 | |||
| 603 | /* Cleanup on error */ | ||
| 604 | |||
| 605 | if (ACPI_FAILURE(status)) { | ||
| 606 | ACPI_FREE(cid_list); | ||
| 607 | } else { | ||
| 608 | *return_cid_list = cid_list; | ||
| 609 | } | ||
| 610 | |||
| 611 | /* On exit, we must delete the _CID return object */ | ||
| 612 | |||
| 613 | acpi_ut_remove_reference(obj_desc); | ||
| 614 | return_ACPI_STATUS(status); | ||
| 615 | } | ||
| 616 | |||
| 617 | /******************************************************************************* | ||
| 618 | * | ||
| 619 | * FUNCTION: acpi_ut_execute_UID | ||
| 620 | * | ||
| 621 | * PARAMETERS: device_node - Node for the device | ||
| 622 | * Uid - Where the UID is returned | ||
| 623 | * | ||
| 624 | * RETURN: Status | ||
| 625 | * | ||
| 626 | * DESCRIPTION: Executes the _UID control method that returns the hardware | ||
| 627 | * ID of the device. | ||
| 628 | * | ||
| 629 | * NOTE: Internal function, no parameter validation | ||
| 630 | * | ||
| 631 | ******************************************************************************/ | ||
| 632 | |||
| 633 | acpi_status | ||
| 634 | acpi_ut_execute_UID(struct acpi_namespace_node *device_node, | ||
| 635 | struct acpica_device_id *uid) | ||
| 636 | { | ||
| 637 | union acpi_operand_object *obj_desc; | ||
| 638 | acpi_status status; | ||
| 639 | |||
| 640 | ACPI_FUNCTION_TRACE(ut_execute_UID); | ||
| 641 | |||
| 642 | status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, | ||
| 643 | ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, | ||
| 644 | &obj_desc); | ||
| 645 | if (ACPI_FAILURE(status)) { | ||
| 646 | return_ACPI_STATUS(status); | ||
| 647 | } | ||
| 648 | |||
| 649 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | ||
| 650 | |||
| 651 | /* Convert the Numeric UID to string */ | ||
| 652 | |||
| 653 | acpi_ex_unsigned_integer_to_string(obj_desc->integer.value, | ||
| 654 | uid->value); | ||
| 655 | } else { | ||
| 656 | /* Copy the String UID from the returned object */ | ||
| 657 | |||
| 658 | acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer, | ||
| 659 | sizeof(uid->value)); | ||
| 660 | } | ||
| 661 | 367 | ||
| 662 | /* On exit, we must delete the return object */ | 368 | /* On exit, we must delete the return object */ |
| 663 | 369 | ||
| @@ -716,60 +422,64 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) | |||
| 716 | 422 | ||
| 717 | /******************************************************************************* | 423 | /******************************************************************************* |
| 718 | * | 424 | * |
| 719 | * FUNCTION: acpi_ut_execute_Sxds | 425 | * FUNCTION: acpi_ut_execute_power_methods |
| 720 | * | 426 | * |
| 721 | * PARAMETERS: device_node - Node for the device | 427 | * PARAMETERS: device_node - Node for the device |
| 722 | * Flags - Where the status flags are returned | 428 | * method_names - Array of power method names |
| 429 | * method_count - Number of methods to execute | ||
| 430 | * out_values - Where the power method values are returned | ||
| 723 | * | 431 | * |
| 724 | * RETURN: Status | 432 | * RETURN: Status, out_values |
| 725 | * | 433 | * |
| 726 | * DESCRIPTION: Executes _STA for selected device and stores results in | 434 | * DESCRIPTION: Executes the specified power methods for the device and returns |
| 727 | * *Flags. | 435 | * the result(s). |
| 728 | * | 436 | * |
| 729 | * NOTE: Internal function, no parameter validation | 437 | * NOTE: Internal function, no parameter validation |
| 730 | * | 438 | * |
| 731 | ******************************************************************************/ | 439 | ******************************************************************************/ |
| 732 | 440 | ||
| 733 | acpi_status | 441 | acpi_status |
| 734 | acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest) | 442 | acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, |
| 443 | const char **method_names, | ||
| 444 | u8 method_count, u8 *out_values) | ||
| 735 | { | 445 | { |
| 736 | union acpi_operand_object *obj_desc; | 446 | union acpi_operand_object *obj_desc; |
| 737 | acpi_status status; | 447 | acpi_status status; |
| 448 | acpi_status final_status = AE_NOT_FOUND; | ||
| 738 | u32 i; | 449 | u32 i; |
| 739 | 450 | ||
| 740 | ACPI_FUNCTION_TRACE(ut_execute_sxds); | 451 | ACPI_FUNCTION_TRACE(ut_execute_power_methods); |
| 741 | 452 | ||
| 742 | for (i = 0; i < 4; i++) { | 453 | for (i = 0; i < method_count; i++) { |
| 743 | highest[i] = 0xFF; | 454 | /* |
| 455 | * Execute the power method (_sx_d or _sx_w). The only allowable | ||
| 456 | * return type is an Integer. | ||
| 457 | */ | ||
| 744 | status = acpi_ut_evaluate_object(device_node, | 458 | status = acpi_ut_evaluate_object(device_node, |
| 745 | ACPI_CAST_PTR(char, | 459 | ACPI_CAST_PTR(char, |
| 746 | acpi_gbl_highest_dstate_names | 460 | method_names[i]), |
| 747 | [i]), | ||
| 748 | ACPI_BTYPE_INTEGER, &obj_desc); | 461 | ACPI_BTYPE_INTEGER, &obj_desc); |
| 749 | if (ACPI_FAILURE(status)) { | 462 | if (ACPI_SUCCESS(status)) { |
| 750 | if (status != AE_NOT_FOUND) { | 463 | out_values[i] = (u8)obj_desc->integer.value; |
| 751 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 752 | "%s on Device %4.4s, %s\n", | ||
| 753 | ACPI_CAST_PTR(char, | ||
| 754 | acpi_gbl_highest_dstate_names | ||
| 755 | [i]), | ||
| 756 | acpi_ut_get_node_name | ||
| 757 | (device_node), | ||
| 758 | acpi_format_exception | ||
| 759 | (status))); | ||
| 760 | |||
| 761 | return_ACPI_STATUS(status); | ||
| 762 | } | ||
| 763 | } else { | ||
| 764 | /* Extract the Dstate value */ | ||
| 765 | |||
| 766 | highest[i] = (u8) obj_desc->integer.value; | ||
| 767 | 464 | ||
| 768 | /* Delete the return object */ | 465 | /* Delete the return object */ |
| 769 | 466 | ||
| 770 | acpi_ut_remove_reference(obj_desc); | 467 | acpi_ut_remove_reference(obj_desc); |
| 468 | final_status = AE_OK; /* At least one value is valid */ | ||
| 469 | continue; | ||
| 771 | } | 470 | } |
| 471 | |||
| 472 | out_values[i] = ACPI_UINT8_MAX; | ||
| 473 | if (status == AE_NOT_FOUND) { | ||
| 474 | continue; /* Ignore if not found */ | ||
| 475 | } | ||
| 476 | |||
| 477 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 478 | "Failed %s on Device %4.4s, %s\n", | ||
| 479 | ACPI_CAST_PTR(char, method_names[i]), | ||
| 480 | acpi_ut_get_node_name(device_node), | ||
| 481 | acpi_format_exception(status))); | ||
| 772 | } | 482 | } |
| 773 | 483 | ||
| 774 | return_ACPI_STATUS(AE_OK); | 484 | return_ACPI_STATUS(final_status); |
| 775 | } | 485 | } |
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 59e46f257c02..3f2c68f4e959 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c | |||
| @@ -90,7 +90,15 @@ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { | |||
| 90 | "\\_S5_" | 90 | "\\_S5_" |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | const char *acpi_gbl_highest_dstate_names[4] = { | 93 | const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS] = { |
| 94 | "_S0W", | ||
| 95 | "_S1W", | ||
| 96 | "_S2W", | ||
| 97 | "_S3W", | ||
| 98 | "_S4W" | ||
| 99 | }; | ||
| 100 | |||
| 101 | const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = { | ||
| 94 | "_S1D", | 102 | "_S1D", |
| 95 | "_S2D", | 103 | "_S2D", |
| 96 | "_S3D", | 104 | "_S3D", |
| @@ -351,6 +359,7 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { | |||
| 351 | "SMBus", | 359 | "SMBus", |
| 352 | "SystemCMOS", | 360 | "SystemCMOS", |
| 353 | "PCIBARTarget", | 361 | "PCIBARTarget", |
| 362 | "IPMI", | ||
| 354 | "DataTable" | 363 | "DataTable" |
| 355 | }; | 364 | }; |
| 356 | 365 | ||
| @@ -798,6 +807,7 @@ acpi_status acpi_ut_init_globals(void) | |||
| 798 | 807 | ||
| 799 | /* Namespace */ | 808 | /* Namespace */ |
| 800 | 809 | ||
| 810 | acpi_gbl_module_code_list = NULL; | ||
| 801 | acpi_gbl_root_node = NULL; | 811 | acpi_gbl_root_node = NULL; |
| 802 | acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; | 812 | acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; |
| 803 | acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; | 813 | acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; |
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c new file mode 100644 index 000000000000..52eaae404554 --- /dev/null +++ b/drivers/acpi/acpica/utids.c | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * Module Name: utids - support for device IDs - HID, UID, CID | ||
| 4 | * | ||
| 5 | *****************************************************************************/ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * Copyright (C) 2000 - 2009, Intel Corp. | ||
| 9 | * All rights reserved. | ||
| 10 | * | ||
| 11 | * Redistribution and use in source and binary forms, with or without | ||
| 12 | * modification, are permitted provided that the following conditions | ||
| 13 | * are met: | ||
| 14 | * 1. Redistributions of source code must retain the above copyright | ||
| 15 | * notice, this list of conditions, and the following disclaimer, | ||
| 16 | * without modification. | ||
| 17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
| 18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
| 19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
| 20 | * including a substantially similar Disclaimer requirement for further | ||
| 21 | * binary redistribution. | ||
| 22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
| 23 | * of any contributors may be used to endorse or promote products derived | ||
| 24 | * from this software without specific prior written permission. | ||
| 25 | * | ||
| 26 | * Alternatively, this software may be distributed under the terms of the | ||
| 27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
| 28 | * Software Foundation. | ||
| 29 | * | ||
| 30 | * NO WARRANTY | ||
| 31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
| 34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
| 40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 41 | * POSSIBILITY OF SUCH DAMAGES. | ||
| 42 | */ | ||
| 43 | |||
| 44 | #include <acpi/acpi.h> | ||
| 45 | #include "accommon.h" | ||
| 46 | #include "acinterp.h" | ||
| 47 | |||
| 48 | #define _COMPONENT ACPI_UTILITIES | ||
| 49 | ACPI_MODULE_NAME("utids") | ||
| 50 | |||
| 51 | /* Local prototypes */ | ||
| 52 | static void acpi_ut_copy_id_string(char *destination, char *source); | ||
| 53 | |||
| 54 | /******************************************************************************* | ||
| 55 | * | ||
| 56 | * FUNCTION: acpi_ut_copy_id_string | ||
| 57 | * | ||
| 58 | * PARAMETERS: Destination - Where to copy the string | ||
| 59 | * Source - Source string | ||
| 60 | * | ||
| 61 | * RETURN: None | ||
| 62 | * | ||
| 63 | * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. | ||
| 64 | * Performs removal of a leading asterisk if present -- workaround | ||
| 65 | * for a known issue on a bunch of machines. | ||
| 66 | * | ||
| 67 | ******************************************************************************/ | ||
| 68 | |||
| 69 | static void acpi_ut_copy_id_string(char *destination, char *source) | ||
| 70 | { | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Workaround for ID strings that have a leading asterisk. This construct | ||
| 74 | * is not allowed by the ACPI specification (ID strings must be | ||
| 75 | * alphanumeric), but enough existing machines have this embedded in their | ||
| 76 | * ID strings that the following code is useful. | ||
| 77 | */ | ||
| 78 | if (*source == '*') { | ||
| 79 | source++; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* Do the actual copy */ | ||
| 83 | |||
| 84 | ACPI_STRCPY(destination, source); | ||
| 85 | } | ||
| 86 | |||
| 87 | /******************************************************************************* | ||
| 88 | * | ||
| 89 | * FUNCTION: acpi_ut_execute_HID | ||
| 90 | * | ||
| 91 | * PARAMETERS: device_node - Node for the device | ||
| 92 | * return_id - Where the string HID is returned | ||
| 93 | * | ||
| 94 | * RETURN: Status | ||
| 95 | * | ||
| 96 | * DESCRIPTION: Executes the _HID control method that returns the hardware | ||
| 97 | * ID of the device. The HID is either an 32-bit encoded EISAID | ||
| 98 | * Integer or a String. A string is always returned. An EISAID | ||
| 99 | * is converted to a string. | ||
| 100 | * | ||
| 101 | * NOTE: Internal function, no parameter validation | ||
| 102 | * | ||
| 103 | ******************************************************************************/ | ||
| 104 | |||
| 105 | acpi_status | ||
| 106 | acpi_ut_execute_HID(struct acpi_namespace_node *device_node, | ||
| 107 | struct acpica_device_id **return_id) | ||
| 108 | { | ||
| 109 | union acpi_operand_object *obj_desc; | ||
| 110 | struct acpica_device_id *hid; | ||
| 111 | u32 length; | ||
| 112 | acpi_status status; | ||
| 113 | |||
| 114 | ACPI_FUNCTION_TRACE(ut_execute_HID); | ||
| 115 | |||
| 116 | status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, | ||
| 117 | ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, | ||
| 118 | &obj_desc); | ||
| 119 | if (ACPI_FAILURE(status)) { | ||
| 120 | return_ACPI_STATUS(status); | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Get the size of the String to be returned, includes null terminator */ | ||
| 124 | |||
| 125 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | ||
| 126 | length = ACPI_EISAID_STRING_SIZE; | ||
| 127 | } else { | ||
| 128 | length = obj_desc->string.length + 1; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Allocate a buffer for the HID */ | ||
| 132 | |||
| 133 | hid = | ||
| 134 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + | ||
| 135 | (acpi_size) length); | ||
| 136 | if (!hid) { | ||
| 137 | status = AE_NO_MEMORY; | ||
| 138 | goto cleanup; | ||
| 139 | } | ||
| 140 | |||
| 141 | /* Area for the string starts after DEVICE_ID struct */ | ||
| 142 | |||
| 143 | hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id)); | ||
| 144 | |||
| 145 | /* Convert EISAID to a string or simply copy existing string */ | ||
| 146 | |||
| 147 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | ||
| 148 | acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value); | ||
| 149 | } else { | ||
| 150 | acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer); | ||
| 151 | } | ||
| 152 | |||
| 153 | hid->length = length; | ||
| 154 | *return_id = hid; | ||
| 155 | |||
| 156 | cleanup: | ||
| 157 | |||
| 158 | /* On exit, we must delete the return object */ | ||
| 159 | |||
| 160 | acpi_ut_remove_reference(obj_desc); | ||
| 161 | return_ACPI_STATUS(status); | ||
| 162 | } | ||
| 163 | |||
| 164 | /******************************************************************************* | ||
| 165 | * | ||
| 166 | * FUNCTION: acpi_ut_execute_UID | ||
| 167 | * | ||
| 168 | * PARAMETERS: device_node - Node for the device | ||
| 169 | * return_id - Where the string UID is returned | ||
| 170 | * | ||
| 171 | * RETURN: Status | ||
| 172 | * | ||
| 173 | * DESCRIPTION: Executes the _UID control method that returns the unique | ||
| 174 | * ID of the device. The UID is either a 64-bit Integer (NOT an | ||
| 175 | * EISAID) or a string. Always returns a string. A 64-bit integer | ||
| 176 | * is converted to a decimal string. | ||
| 177 | * | ||
| 178 | * NOTE: Internal function, no parameter validation | ||
| 179 | * | ||
| 180 | ******************************************************************************/ | ||
| 181 | |||
| 182 | acpi_status | ||
| 183 | acpi_ut_execute_UID(struct acpi_namespace_node *device_node, | ||
| 184 | struct acpica_device_id **return_id) | ||
| 185 | { | ||
| 186 | union acpi_operand_object *obj_desc; | ||
| 187 | struct acpica_device_id *uid; | ||
| 188 | u32 length; | ||
| 189 | acpi_status status; | ||
| 190 | |||
| 191 | ACPI_FUNCTION_TRACE(ut_execute_UID); | ||
| 192 | |||
| 193 | status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, | ||
| 194 | ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, | ||
| 195 | &obj_desc); | ||
| 196 | if (ACPI_FAILURE(status)) { | ||
| 197 | return_ACPI_STATUS(status); | ||
| 198 | } | ||
| 199 | |||
| 200 | /* Get the size of the String to be returned, includes null terminator */ | ||
| 201 | |||
| 202 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | ||
| 203 | length = ACPI_MAX64_DECIMAL_DIGITS + 1; | ||
| 204 | } else { | ||
| 205 | length = obj_desc->string.length + 1; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Allocate a buffer for the UID */ | ||
| 209 | |||
| 210 | uid = | ||
| 211 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + | ||
| 212 | (acpi_size) length); | ||
| 213 | if (!uid) { | ||
| 214 | status = AE_NO_MEMORY; | ||
| 215 | goto cleanup; | ||
| 216 | } | ||
| 217 | |||
| 218 | /* Area for the string starts after DEVICE_ID struct */ | ||
| 219 | |||
| 220 | uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id)); | ||
| 221 | |||
| 222 | /* Convert an Integer to string, or just copy an existing string */ | ||
| 223 | |||
| 224 | if (obj_desc->common.type == ACPI_TYPE_INTEGER) { | ||
| 225 | acpi_ex_integer_to_string(uid->string, obj_desc->integer.value); | ||
| 226 | } else { | ||
| 227 | acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer); | ||
| 228 | } | ||
| 229 | |||
| 230 | uid->length = length; | ||
| 231 | *return_id = uid; | ||
| 232 | |||
| 233 | cleanup: | ||
| 234 | |||
| 235 | /* On exit, we must delete the return object */ | ||
| 236 | |||
| 237 | acpi_ut_remove_reference(obj_desc); | ||
| 238 | return_ACPI_STATUS(status); | ||
| 239 | } | ||
| 240 | |||
| 241 | /******************************************************************************* | ||
| 242 | * | ||
| 243 | * FUNCTION: acpi_ut_execute_CID | ||
| 244 | * | ||
| 245 | * PARAMETERS: device_node - Node for the device | ||
| 246 | * return_cid_list - Where the CID list is returned | ||
| 247 | * | ||
| 248 | * RETURN: Status, list of CID strings | ||
| 249 | * | ||
| 250 | * DESCRIPTION: Executes the _CID control method that returns one or more | ||
| 251 | * compatible hardware IDs for the device. | ||
| 252 | * | ||
| 253 | * NOTE: Internal function, no parameter validation | ||
| 254 | * | ||
| 255 | * A _CID method can return either a single compatible ID or a package of | ||
| 256 | * compatible IDs. Each compatible ID can be one of the following: | ||
| 257 | * 1) Integer (32 bit compressed EISA ID) or | ||
| 258 | * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") | ||
| 259 | * | ||
| 260 | * The Integer CIDs are converted to string format by this function. | ||
| 261 | * | ||
| 262 | ******************************************************************************/ | ||
| 263 | |||
| 264 | acpi_status | ||
| 265 | acpi_ut_execute_CID(struct acpi_namespace_node *device_node, | ||
| 266 | struct acpica_device_id_list **return_cid_list) | ||
| 267 | { | ||
| 268 | union acpi_operand_object **cid_objects; | ||
| 269 | union acpi_operand_object *obj_desc; | ||
| 270 | struct acpica_device_id_list *cid_list; | ||
| 271 | char *next_id_string; | ||
| 272 | u32 string_area_size; | ||
| 273 | u32 length; | ||
| 274 | u32 cid_list_size; | ||
| 275 | acpi_status status; | ||
| 276 | u32 count; | ||
| 277 | u32 i; | ||
| 278 | |||
| 279 | ACPI_FUNCTION_TRACE(ut_execute_CID); | ||
| 280 | |||
| 281 | /* Evaluate the _CID method for this device */ | ||
| 282 | |||
| 283 | status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, | ||
| 284 | ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ||
| 285 | | ACPI_BTYPE_PACKAGE, &obj_desc); | ||
| 286 | if (ACPI_FAILURE(status)) { | ||
| 287 | return_ACPI_STATUS(status); | ||
| 288 | } | ||
| 289 | |||
| 290 | /* | ||
| 291 | * Get the count and size of the returned _CIDs. _CID can return either | ||
| 292 | * a Package of Integers/Strings or a single Integer or String. | ||
| 293 | * Note: This section also validates that all CID elements are of the | ||
| 294 | * correct type (Integer or String). | ||
| 295 | */ | ||
| 296 | if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { | ||
| 297 | count = obj_desc->package.count; | ||
| 298 | cid_objects = obj_desc->package.elements; | ||
| 299 | } else { /* Single Integer or String CID */ | ||
| 300 | |||
| 301 | count = 1; | ||
| 302 | cid_objects = &obj_desc; | ||
| 303 | } | ||
| 304 | |||
| 305 | string_area_size = 0; | ||
| 306 | for (i = 0; i < count; i++) { | ||
| 307 | |||
| 308 | /* String lengths include null terminator */ | ||
| 309 | |||
| 310 | switch (cid_objects[i]->common.type) { | ||
| 311 | case ACPI_TYPE_INTEGER: | ||
| 312 | string_area_size += ACPI_EISAID_STRING_SIZE; | ||
| 313 | break; | ||
| 314 | |||
| 315 | case ACPI_TYPE_STRING: | ||
| 316 | string_area_size += cid_objects[i]->string.length + 1; | ||
| 317 | break; | ||
| 318 | |||
| 319 | default: | ||
| 320 | status = AE_TYPE; | ||
| 321 | goto cleanup; | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | /* | ||
| 326 | * Now that we know the length of the CIDs, allocate return buffer: | ||
| 327 | * 1) Size of the base structure + | ||
| 328 | * 2) Size of the CID DEVICE_ID array + | ||
| 329 | * 3) Size of the actual CID strings | ||
| 330 | */ | ||
| 331 | cid_list_size = sizeof(struct acpica_device_id_list) + | ||
| 332 | ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size; | ||
| 333 | |||
| 334 | cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size); | ||
| 335 | if (!cid_list) { | ||
| 336 | status = AE_NO_MEMORY; | ||
| 337 | goto cleanup; | ||
| 338 | } | ||
| 339 | |||
| 340 | /* Area for CID strings starts after the CID DEVICE_ID array */ | ||
| 341 | |||
| 342 | next_id_string = ACPI_CAST_PTR(char, cid_list->ids) + | ||
| 343 | ((acpi_size) count * sizeof(struct acpica_device_id)); | ||
| 344 | |||
| 345 | /* Copy/convert the CIDs to the return buffer */ | ||
| 346 | |||
| 347 | for (i = 0; i < count; i++) { | ||
| 348 | if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) { | ||
| 349 | |||
| 350 | /* Convert the Integer (EISAID) CID to a string */ | ||
| 351 | |||
| 352 | acpi_ex_eisa_id_to_string(next_id_string, | ||
| 353 | cid_objects[i]->integer. | ||
| 354 | value); | ||
| 355 | length = ACPI_EISAID_STRING_SIZE; | ||
| 356 | } else { /* ACPI_TYPE_STRING */ | ||
| 357 | |||
| 358 | /* Copy the String CID from the returned object */ | ||
| 359 | |||
| 360 | acpi_ut_copy_id_string(next_id_string, | ||
| 361 | cid_objects[i]->string.pointer); | ||
| 362 | length = cid_objects[i]->string.length + 1; | ||
| 363 | } | ||
| 364 | |||
| 365 | cid_list->ids[i].string = next_id_string; | ||
| 366 | cid_list->ids[i].length = length; | ||
| 367 | next_id_string += length; | ||
| 368 | } | ||
| 369 | |||
| 370 | /* Finish the CID list */ | ||
| 371 | |||
| 372 | cid_list->count = count; | ||
| 373 | cid_list->list_size = cid_list_size; | ||
| 374 | *return_cid_list = cid_list; | ||
| 375 | |||
| 376 | cleanup: | ||
| 377 | |||
| 378 | /* On exit, we must delete the _CID return object */ | ||
| 379 | |||
| 380 | acpi_ut_remove_reference(obj_desc); | ||
| 381 | return_ACPI_STATUS(status); | ||
| 382 | } | ||
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index a54ca84eb362..9d0919ebf7b0 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c | |||
| @@ -99,33 +99,19 @@ static void acpi_ut_terminate(void) | |||
| 99 | * | 99 | * |
| 100 | * FUNCTION: acpi_ut_subsystem_shutdown | 100 | * FUNCTION: acpi_ut_subsystem_shutdown |
| 101 | * | 101 | * |
| 102 | * PARAMETERS: none | 102 | * PARAMETERS: None |
| 103 | * | 103 | * |
| 104 | * RETURN: none | 104 | * RETURN: None |
| 105 | * | 105 | * |
| 106 | * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex | 106 | * DESCRIPTION: Shutdown the various components. Do not delete the mutex |
| 107 | * objects here -- because the AML debugger may be still running. | 107 | * objects here, because the AML debugger may be still running. |
| 108 | * | 108 | * |
| 109 | ******************************************************************************/ | 109 | ******************************************************************************/ |
| 110 | 110 | ||
| 111 | void acpi_ut_subsystem_shutdown(void) | 111 | void acpi_ut_subsystem_shutdown(void) |
| 112 | { | 112 | { |
| 113 | |||
| 114 | ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); | 113 | ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); |
| 115 | 114 | ||
| 116 | /* Just exit if subsystem is already shutdown */ | ||
| 117 | |||
| 118 | if (acpi_gbl_shutdown) { | ||
| 119 | ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); | ||
| 120 | return_VOID; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Subsystem appears active, go ahead and shut it down */ | ||
| 124 | |||
| 125 | acpi_gbl_shutdown = TRUE; | ||
| 126 | acpi_gbl_startup_flags = 0; | ||
| 127 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); | ||
| 128 | |||
| 129 | #ifndef ACPI_ASL_COMPILER | 115 | #ifndef ACPI_ASL_COMPILER |
| 130 | 116 | ||
| 131 | /* Close the acpi_event Handling */ | 117 | /* Close the acpi_event Handling */ |
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index fbe782348b0b..61f6315fce9f 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c | |||
| @@ -50,6 +50,11 @@ | |||
| 50 | #define _COMPONENT ACPI_UTILITIES | 50 | #define _COMPONENT ACPI_UTILITIES |
| 51 | ACPI_MODULE_NAME("utmisc") | 51 | ACPI_MODULE_NAME("utmisc") |
| 52 | 52 | ||
| 53 | /* | ||
| 54 | * Common suffix for messages | ||
| 55 | */ | ||
| 56 | #define ACPI_COMMON_MSG_SUFFIX \ | ||
| 57 | acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) | ||
| 53 | /******************************************************************************* | 58 | /******************************************************************************* |
| 54 | * | 59 | * |
| 55 | * FUNCTION: acpi_ut_validate_exception | 60 | * FUNCTION: acpi_ut_validate_exception |
| @@ -120,6 +125,34 @@ const char *acpi_ut_validate_exception(acpi_status status) | |||
| 120 | 125 | ||
| 121 | /******************************************************************************* | 126 | /******************************************************************************* |
| 122 | * | 127 | * |
| 128 | * FUNCTION: acpi_ut_is_pci_root_bridge | ||
| 129 | * | ||
| 130 | * PARAMETERS: Id - The HID/CID in string format | ||
| 131 | * | ||
| 132 | * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge | ||
| 133 | * | ||
| 134 | * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. | ||
| 135 | * | ||
| 136 | ******************************************************************************/ | ||
| 137 | |||
| 138 | u8 acpi_ut_is_pci_root_bridge(char *id) | ||
| 139 | { | ||
| 140 | |||
| 141 | /* | ||
| 142 | * Check if this is a PCI root bridge. | ||
| 143 | * ACPI 3.0+: check for a PCI Express root also. | ||
| 144 | */ | ||
| 145 | if (!(ACPI_STRCMP(id, | ||
| 146 | PCI_ROOT_HID_STRING)) || | ||
| 147 | !(ACPI_STRCMP(id, PCI_EXPRESS_ROOT_HID_STRING))) { | ||
| 148 | return (TRUE); | ||
| 149 | } | ||
| 150 | |||
| 151 | return (FALSE); | ||
| 152 | } | ||
| 153 | |||
| 154 | /******************************************************************************* | ||
| 155 | * | ||
| 123 | * FUNCTION: acpi_ut_is_aml_table | 156 | * FUNCTION: acpi_ut_is_aml_table |
| 124 | * | 157 | * |
| 125 | * PARAMETERS: Table - An ACPI table | 158 | * PARAMETERS: Table - An ACPI table |
| @@ -1037,8 +1070,7 @@ acpi_error(const char *module_name, u32 line_number, const char *format, ...) | |||
| 1037 | 1070 | ||
| 1038 | va_start(args, format); | 1071 | va_start(args, format); |
| 1039 | acpi_os_vprintf(format, args); | 1072 | acpi_os_vprintf(format, args); |
| 1040 | acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name, | 1073 | ACPI_COMMON_MSG_SUFFIX; |
| 1041 | line_number); | ||
| 1042 | va_end(args); | 1074 | va_end(args); |
| 1043 | } | 1075 | } |
| 1044 | 1076 | ||
| @@ -1052,8 +1084,7 @@ acpi_exception(const char *module_name, | |||
| 1052 | 1084 | ||
| 1053 | va_start(args, format); | 1085 | va_start(args, format); |
| 1054 | acpi_os_vprintf(format, args); | 1086 | acpi_os_vprintf(format, args); |
| 1055 | acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name, | 1087 | ACPI_COMMON_MSG_SUFFIX; |
| 1056 | line_number); | ||
| 1057 | va_end(args); | 1088 | va_end(args); |
| 1058 | } | 1089 | } |
| 1059 | 1090 | ||
| @@ -1066,8 +1097,7 @@ acpi_warning(const char *module_name, u32 line_number, const char *format, ...) | |||
| 1066 | 1097 | ||
| 1067 | va_start(args, format); | 1098 | va_start(args, format); |
| 1068 | acpi_os_vprintf(format, args); | 1099 | acpi_os_vprintf(format, args); |
| 1069 | acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name, | 1100 | ACPI_COMMON_MSG_SUFFIX; |
| 1070 | line_number); | ||
| 1071 | va_end(args); | 1101 | va_end(args); |
| 1072 | } | 1102 | } |
| 1073 | 1103 | ||
| @@ -1088,3 +1118,46 @@ ACPI_EXPORT_SYMBOL(acpi_error) | |||
| 1088 | ACPI_EXPORT_SYMBOL(acpi_exception) | 1118 | ACPI_EXPORT_SYMBOL(acpi_exception) |
| 1089 | ACPI_EXPORT_SYMBOL(acpi_warning) | 1119 | ACPI_EXPORT_SYMBOL(acpi_warning) |
| 1090 | ACPI_EXPORT_SYMBOL(acpi_info) | 1120 | ACPI_EXPORT_SYMBOL(acpi_info) |
| 1121 | |||
| 1122 | /******************************************************************************* | ||
| 1123 | * | ||
| 1124 | * FUNCTION: acpi_ut_predefined_warning | ||
| 1125 | * | ||
| 1126 | * PARAMETERS: module_name - Caller's module name (for error output) | ||
| 1127 | * line_number - Caller's line number (for error output) | ||
| 1128 | * Pathname - Full pathname to the node | ||
| 1129 | * node_flags - From Namespace node for the method/object | ||
| 1130 | * Format - Printf format string + additional args | ||
| 1131 | * | ||
| 1132 | * RETURN: None | ||
| 1133 | * | ||
| 1134 | * DESCRIPTION: Warnings for the predefined validation module. Messages are | ||
| 1135 | * only emitted the first time a problem with a particular | ||
| 1136 | * method/object is detected. This prevents a flood of error | ||
| 1137 | * messages for methods that are repeatedly evaluated. | ||
| 1138 | * | ||
| 1139 | ******************************************************************************/ | ||
| 1140 | |||
| 1141 | void ACPI_INTERNAL_VAR_XFACE | ||
| 1142 | acpi_ut_predefined_warning(const char *module_name, | ||
| 1143 | u32 line_number, | ||
| 1144 | char *pathname, | ||
| 1145 | u8 node_flags, const char *format, ...) | ||
| 1146 | { | ||
| 1147 | va_list args; | ||
| 1148 | |||
| 1149 | /* | ||
| 1150 | * Warning messages for this method/object will be disabled after the | ||
| 1151 | * first time a validation fails or an object is successfully repaired. | ||
| 1152 | */ | ||
| 1153 | if (node_flags & ANOBJ_EVALUATED) { | ||
| 1154 | return; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | acpi_os_printf("ACPI Warning for %s: ", pathname); | ||
| 1158 | |||
| 1159 | va_start(args, format); | ||
| 1160 | acpi_os_vprintf(format, args); | ||
| 1161 | ACPI_COMMON_MSG_SUFFIX; | ||
| 1162 | va_end(args); | ||
| 1163 | } | ||
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 078a22728c6b..b1f5f680bc78 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c | |||
| @@ -251,6 +251,16 @@ acpi_status acpi_initialize_objects(u32 flags) | |||
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | /* | 253 | /* |
| 254 | * Execute any module-level code that was detected during the table load | ||
| 255 | * phase. Although illegal since ACPI 2.0, there are many machines that | ||
| 256 | * contain this type of code. Each block of detected executable AML code | ||
| 257 | * outside of any control method is wrapped with a temporary control | ||
| 258 | * method object and placed on a global list. The methods on this list | ||
| 259 | * are executed below. | ||
| 260 | */ | ||
| 261 | acpi_ns_exec_module_code_list(); | ||
| 262 | |||
| 263 | /* | ||
| 254 | * Initialize the objects that remain uninitialized. This runs the | 264 | * Initialize the objects that remain uninitialized. This runs the |
| 255 | * executable AML that may be part of the declaration of these objects: | 265 | * executable AML that may be part of the declaration of these objects: |
| 256 | * operation_regions, buffer_fields, Buffers, and Packages. | 266 | * operation_regions, buffer_fields, Buffers, and Packages. |
| @@ -318,7 +328,7 @@ ACPI_EXPORT_SYMBOL(acpi_initialize_objects) | |||
| 318 | * | 328 | * |
| 319 | * RETURN: Status | 329 | * RETURN: Status |
| 320 | * | 330 | * |
| 321 | * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. | 331 | * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. |
| 322 | * | 332 | * |
| 323 | ******************************************************************************/ | 333 | ******************************************************************************/ |
| 324 | acpi_status acpi_terminate(void) | 334 | acpi_status acpi_terminate(void) |
| @@ -327,6 +337,19 @@ acpi_status acpi_terminate(void) | |||
| 327 | 337 | ||
| 328 | ACPI_FUNCTION_TRACE(acpi_terminate); | 338 | ACPI_FUNCTION_TRACE(acpi_terminate); |
| 329 | 339 | ||
| 340 | /* Just exit if subsystem is already shutdown */ | ||
| 341 | |||
| 342 | if (acpi_gbl_shutdown) { | ||
| 343 | ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); | ||
| 344 | return_ACPI_STATUS(AE_OK); | ||
| 345 | } | ||
| 346 | |||
| 347 | /* Subsystem appears active, go ahead and shut it down */ | ||
| 348 | |||
| 349 | acpi_gbl_shutdown = TRUE; | ||
| 350 | acpi_gbl_startup_flags = 0; | ||
| 351 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); | ||
| 352 | |||
| 330 | /* Terminate the AML Debugger if present */ | 353 | /* Terminate the AML Debugger if present */ |
| 331 | 354 | ||
| 332 | ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); | 355 | ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); |
| @@ -353,6 +376,7 @@ acpi_status acpi_terminate(void) | |||
| 353 | } | 376 | } |
| 354 | 377 | ||
| 355 | ACPI_EXPORT_SYMBOL(acpi_terminate) | 378 | ACPI_EXPORT_SYMBOL(acpi_terminate) |
| 379 | |||
| 356 | #ifndef ACPI_ASL_COMPILER | 380 | #ifndef ACPI_ASL_COMPILER |
| 357 | #ifdef ACPI_FUTURE_USAGE | 381 | #ifdef ACPI_FUTURE_USAGE |
| 358 | /******************************************************************************* | 382 | /******************************************************************************* |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 58b4517ce712..3f4602b8f287 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
| 33 | #include <linux/async.h> | 33 | #include <linux/async.h> |
| 34 | #include <linux/dmi.h> | ||
| 34 | 35 | ||
| 35 | #ifdef CONFIG_ACPI_PROCFS_POWER | 36 | #ifdef CONFIG_ACPI_PROCFS_POWER |
| 36 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
| @@ -45,6 +46,8 @@ | |||
| 45 | #include <linux/power_supply.h> | 46 | #include <linux/power_supply.h> |
| 46 | #endif | 47 | #endif |
| 47 | 48 | ||
| 49 | #define PREFIX "ACPI: " | ||
| 50 | |||
| 48 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF | 51 | #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF |
| 49 | 52 | ||
| 50 | #define ACPI_BATTERY_CLASS "battery" | 53 | #define ACPI_BATTERY_CLASS "battery" |
| @@ -85,6 +88,10 @@ static const struct acpi_device_id battery_device_ids[] = { | |||
| 85 | 88 | ||
| 86 | MODULE_DEVICE_TABLE(acpi, battery_device_ids); | 89 | MODULE_DEVICE_TABLE(acpi, battery_device_ids); |
| 87 | 90 | ||
| 91 | /* For buggy DSDTs that report negative 16-bit values for either charging | ||
| 92 | * or discharging current and/or report 0 as 65536 due to bad math. | ||
| 93 | */ | ||
| 94 | #define QUIRK_SIGNED16_CURRENT 0x0001 | ||
| 88 | 95 | ||
| 89 | struct acpi_battery { | 96 | struct acpi_battery { |
| 90 | struct mutex lock; | 97 | struct mutex lock; |
| @@ -112,6 +119,7 @@ struct acpi_battery { | |||
| 112 | int state; | 119 | int state; |
| 113 | int power_unit; | 120 | int power_unit; |
| 114 | u8 alarm_present; | 121 | u8 alarm_present; |
| 122 | long quirks; | ||
| 115 | }; | 123 | }; |
| 116 | 124 | ||
| 117 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); | 125 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); |
| @@ -390,6 +398,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
| 390 | state_offsets, ARRAY_SIZE(state_offsets)); | 398 | state_offsets, ARRAY_SIZE(state_offsets)); |
| 391 | battery->update_time = jiffies; | 399 | battery->update_time = jiffies; |
| 392 | kfree(buffer.pointer); | 400 | kfree(buffer.pointer); |
| 401 | |||
| 402 | if ((battery->quirks & QUIRK_SIGNED16_CURRENT) && | ||
| 403 | battery->rate_now != -1) | ||
| 404 | battery->rate_now = abs((s16)battery->rate_now); | ||
| 405 | |||
| 393 | return result; | 406 | return result; |
| 394 | } | 407 | } |
| 395 | 408 | ||
| @@ -495,6 +508,14 @@ static void sysfs_remove_battery(struct acpi_battery *battery) | |||
| 495 | } | 508 | } |
| 496 | #endif | 509 | #endif |
| 497 | 510 | ||
| 511 | static void acpi_battery_quirks(struct acpi_battery *battery) | ||
| 512 | { | ||
| 513 | battery->quirks = 0; | ||
| 514 | if (dmi_name_in_vendors("Acer") && battery->power_unit) { | ||
| 515 | battery->quirks |= QUIRK_SIGNED16_CURRENT; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 498 | static int acpi_battery_update(struct acpi_battery *battery) | 519 | static int acpi_battery_update(struct acpi_battery *battery) |
| 499 | { | 520 | { |
| 500 | int result, old_present = acpi_battery_present(battery); | 521 | int result, old_present = acpi_battery_present(battery); |
| @@ -513,6 +534,7 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
| 513 | result = acpi_battery_get_info(battery); | 534 | result = acpi_battery_get_info(battery); |
| 514 | if (result) | 535 | if (result) |
| 515 | return result; | 536 | return result; |
| 537 | acpi_battery_quirks(battery); | ||
| 516 | acpi_battery_init_alarm(battery); | 538 | acpi_battery_init_alarm(battery); |
| 517 | } | 539 | } |
| 518 | #ifdef CONFIG_ACPI_SYSFS_POWER | 540 | #ifdef CONFIG_ACPI_SYSFS_POWER |
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 0c4ca4d318b3..e56b2a7b53db 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
| 35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
| 36 | 36 | ||
| 37 | #include "internal.h" | ||
| 38 | |||
| 37 | enum acpi_blacklist_predicates { | 39 | enum acpi_blacklist_predicates { |
| 38 | all_versions, | 40 | all_versions, |
| 39 | less_than_or_equal, | 41 | less_than_or_equal, |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 2876fc70c3a9..135fbfe1825c 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
| 39 | #include <acpi/acpi_bus.h> | 39 | #include <acpi/acpi_bus.h> |
| 40 | #include <acpi/acpi_drivers.h> | 40 | #include <acpi/acpi_drivers.h> |
| 41 | #include <linux/dmi.h> | ||
| 41 | 42 | ||
| 42 | #include "internal.h" | 43 | #include "internal.h" |
| 43 | 44 | ||
| @@ -141,7 +142,7 @@ int acpi_bus_get_status(struct acpi_device *device) | |||
| 141 | EXPORT_SYMBOL(acpi_bus_get_status); | 142 | EXPORT_SYMBOL(acpi_bus_get_status); |
| 142 | 143 | ||
| 143 | void acpi_bus_private_data_handler(acpi_handle handle, | 144 | void acpi_bus_private_data_handler(acpi_handle handle, |
| 144 | u32 function, void *context) | 145 | void *context) |
| 145 | { | 146 | { |
| 146 | return; | 147 | return; |
| 147 | } | 148 | } |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 9195deba9d94..d295bdccc09c 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
| 34 | #include <acpi/acpi_drivers.h> | 34 | #include <acpi/acpi_drivers.h> |
| 35 | 35 | ||
| 36 | #define PREFIX "ACPI: " | ||
| 37 | |||
| 36 | #define ACPI_BUTTON_CLASS "button" | 38 | #define ACPI_BUTTON_CLASS "button" |
| 37 | #define ACPI_BUTTON_FILE_INFO "info" | 39 | #define ACPI_BUTTON_FILE_INFO "info" |
| 38 | #define ACPI_BUTTON_FILE_STATE "state" | 40 | #define ACPI_BUTTON_FILE_STATE "state" |
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 332fe4b21708..6c9ee68e46fb 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include <acpi/acpi_bus.h> | 28 | #include <acpi/acpi_bus.h> |
| 29 | #include <acpi/acpi_drivers.h> | 29 | #include <acpi/acpi_drivers.h> |
| 30 | 30 | ||
| 31 | #define PREFIX "ACPI: " | ||
| 32 | |||
| 31 | ACPI_MODULE_NAME("cm_sbs"); | 33 | ACPI_MODULE_NAME("cm_sbs"); |
| 32 | #define ACPI_AC_CLASS "ac_adapter" | 34 | #define ACPI_AC_CLASS "ac_adapter" |
| 33 | #define ACPI_BATTERY_CLASS "battery" | 35 | #define ACPI_BATTERY_CLASS "battery" |
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index fe0cdf83641a..642bb305cb65 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
| @@ -35,6 +35,8 @@ | |||
| 35 | #include <acpi/acpi_drivers.h> | 35 | #include <acpi/acpi_drivers.h> |
| 36 | #include <acpi/container.h> | 36 | #include <acpi/container.h> |
| 37 | 37 | ||
| 38 | #define PREFIX "ACPI: " | ||
| 39 | |||
| 38 | #define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" | 40 | #define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" |
| 39 | #define ACPI_CONTAINER_CLASS "container" | 41 | #define ACPI_CONTAINER_CLASS "container" |
| 40 | 42 | ||
| @@ -200,20 +202,17 @@ container_walk_namespace_cb(acpi_handle handle, | |||
| 200 | u32 lvl, void *context, void **rv) | 202 | u32 lvl, void *context, void **rv) |
| 201 | { | 203 | { |
| 202 | char *hid = NULL; | 204 | char *hid = NULL; |
| 203 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 204 | struct acpi_device_info *info; | 205 | struct acpi_device_info *info; |
| 205 | acpi_status status; | 206 | acpi_status status; |
| 206 | int *action = context; | 207 | int *action = context; |
| 207 | 208 | ||
| 208 | 209 | status = acpi_get_object_info(handle, &info); | |
| 209 | status = acpi_get_object_info(handle, &buffer); | 210 | if (ACPI_FAILURE(status)) { |
| 210 | if (ACPI_FAILURE(status) || !buffer.pointer) { | ||
| 211 | return AE_OK; | 211 | return AE_OK; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | info = buffer.pointer; | ||
| 215 | if (info->valid & ACPI_VALID_HID) | 214 | if (info->valid & ACPI_VALID_HID) |
| 216 | hid = info->hardware_id.value; | 215 | hid = info->hardware_id.string; |
| 217 | 216 | ||
| 218 | if (hid == NULL) { | 217 | if (hid == NULL) { |
| 219 | goto end; | 218 | goto end; |
| @@ -240,7 +239,7 @@ container_walk_namespace_cb(acpi_handle handle, | |||
| 240 | } | 239 | } |
| 241 | 240 | ||
| 242 | end: | 241 | end: |
| 243 | kfree(buffer.pointer); | 242 | kfree(info); |
| 244 | 243 | ||
| 245 | return AE_OK; | 244 | return AE_OK; |
| 246 | } | 245 | } |
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index a8287be0870e..8a690c3b8e23 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #include <linux/proc_fs.h> | 5 | #include <linux/proc_fs.h> |
| 6 | #include <linux/seq_file.h> | ||
| 6 | #include <linux/init.h> | 7 | #include <linux/init.h> |
| 7 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 8 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| @@ -201,72 +202,54 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state, | |||
| 201 | #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" | 202 | #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" |
| 202 | #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" | 203 | #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" |
| 203 | 204 | ||
| 204 | static int | 205 | static int acpi_system_debug_proc_show(struct seq_file *m, void *v) |
| 205 | acpi_system_read_debug(char *page, | ||
| 206 | char **start, off_t off, int count, int *eof, void *data) | ||
| 207 | { | 206 | { |
| 208 | char *p = page; | ||
| 209 | int size = 0; | ||
| 210 | unsigned int i; | 207 | unsigned int i; |
| 211 | 208 | ||
| 212 | if (off != 0) | 209 | seq_printf(m, "%-25s\tHex SET\n", "Description"); |
| 213 | goto end; | ||
| 214 | 210 | ||
| 215 | p += sprintf(p, "%-25s\tHex SET\n", "Description"); | 211 | switch ((unsigned long)m->private) { |
| 216 | |||
| 217 | switch ((unsigned long)data) { | ||
| 218 | case 0: | 212 | case 0: |
| 219 | for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { | 213 | for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { |
| 220 | p += sprintf(p, "%-25s\t0x%08lX [%c]\n", | 214 | seq_printf(m, "%-25s\t0x%08lX [%c]\n", |
| 221 | acpi_debug_layers[i].name, | 215 | acpi_debug_layers[i].name, |
| 222 | acpi_debug_layers[i].value, | 216 | acpi_debug_layers[i].value, |
| 223 | (acpi_dbg_layer & acpi_debug_layers[i]. | 217 | (acpi_dbg_layer & acpi_debug_layers[i]. |
| 224 | value) ? '*' : ' '); | 218 | value) ? '*' : ' '); |
| 225 | } | 219 | } |
| 226 | p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", | 220 | seq_printf(m, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", |
| 227 | ACPI_ALL_DRIVERS, | 221 | ACPI_ALL_DRIVERS, |
| 228 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) == | 222 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) == |
| 229 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & | 223 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & |
| 230 | ACPI_ALL_DRIVERS) == | 224 | ACPI_ALL_DRIVERS) == |
| 231 | 0 ? ' ' : '-'); | 225 | 0 ? ' ' : '-'); |
| 232 | p += sprintf(p, | 226 | seq_printf(m, |
| 233 | "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n", | 227 | "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n", |
| 234 | acpi_dbg_layer); | 228 | acpi_dbg_layer); |
| 235 | break; | 229 | break; |
| 236 | case 1: | 230 | case 1: |
| 237 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { | 231 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { |
| 238 | p += sprintf(p, "%-25s\t0x%08lX [%c]\n", | 232 | seq_printf(m, "%-25s\t0x%08lX [%c]\n", |
| 239 | acpi_debug_levels[i].name, | 233 | acpi_debug_levels[i].name, |
| 240 | acpi_debug_levels[i].value, | 234 | acpi_debug_levels[i].value, |
| 241 | (acpi_dbg_level & acpi_debug_levels[i]. | 235 | (acpi_dbg_level & acpi_debug_levels[i]. |
| 242 | value) ? '*' : ' '); | 236 | value) ? '*' : ' '); |
| 243 | } | 237 | } |
| 244 | p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n", | 238 | seq_printf(m, "--\ndebug_level = 0x%08X (* = enabled)\n", |
| 245 | acpi_dbg_level); | 239 | acpi_dbg_level); |
| 246 | break; | 240 | break; |
| 247 | default: | ||
| 248 | p += sprintf(p, "Invalid debug option\n"); | ||
| 249 | break; | ||
| 250 | } | 241 | } |
| 242 | return 0; | ||
| 243 | } | ||
| 251 | 244 | ||
| 252 | end: | 245 | static int acpi_system_debug_proc_open(struct inode *inode, struct file *file) |
| 253 | size = (p - page); | 246 | { |
| 254 | if (size <= off + count) | 247 | return single_open(file, acpi_system_debug_proc_show, PDE(inode)->data); |
| 255 | *eof = 1; | ||
| 256 | *start = page + off; | ||
| 257 | size -= off; | ||
| 258 | if (size > count) | ||
| 259 | size = count; | ||
| 260 | if (size < 0) | ||
| 261 | size = 0; | ||
| 262 | |||
| 263 | return size; | ||
| 264 | } | 248 | } |
| 265 | 249 | ||
| 266 | static int | 250 | static ssize_t acpi_system_debug_proc_write(struct file *file, |
| 267 | acpi_system_write_debug(struct file *file, | ||
| 268 | const char __user * buffer, | 251 | const char __user * buffer, |
| 269 | unsigned long count, void *data) | 252 | size_t count, loff_t *pos) |
| 270 | { | 253 | { |
| 271 | char debug_string[12] = { '\0' }; | 254 | char debug_string[12] = { '\0' }; |
| 272 | 255 | ||
| @@ -279,7 +262,7 @@ acpi_system_write_debug(struct file *file, | |||
| 279 | 262 | ||
| 280 | debug_string[count] = '\0'; | 263 | debug_string[count] = '\0'; |
| 281 | 264 | ||
| 282 | switch ((unsigned long)data) { | 265 | switch ((unsigned long)PDE(file->f_path.dentry->d_inode)->data) { |
| 283 | case 0: | 266 | case 0: |
| 284 | acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); | 267 | acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); |
| 285 | break; | 268 | break; |
| @@ -292,6 +275,15 @@ acpi_system_write_debug(struct file *file, | |||
| 292 | 275 | ||
| 293 | return count; | 276 | return count; |
| 294 | } | 277 | } |
| 278 | |||
| 279 | static const struct file_operations acpi_system_debug_proc_fops = { | ||
| 280 | .owner = THIS_MODULE, | ||
| 281 | .open = acpi_system_debug_proc_open, | ||
| 282 | .read = seq_read, | ||
| 283 | .llseek = seq_lseek, | ||
| 284 | .release = single_release, | ||
| 285 | .write = acpi_system_debug_proc_write, | ||
| 286 | }; | ||
| 295 | #endif | 287 | #endif |
| 296 | 288 | ||
| 297 | int __init acpi_debug_init(void) | 289 | int __init acpi_debug_init(void) |
| @@ -303,24 +295,18 @@ int __init acpi_debug_init(void) | |||
| 303 | 295 | ||
| 304 | /* 'debug_layer' [R/W] */ | 296 | /* 'debug_layer' [R/W] */ |
| 305 | name = ACPI_SYSTEM_FILE_DEBUG_LAYER; | 297 | name = ACPI_SYSTEM_FILE_DEBUG_LAYER; |
| 306 | entry = | 298 | entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, |
| 307 | create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, | 299 | acpi_root_dir, &acpi_system_debug_proc_fops, |
| 308 | acpi_root_dir, acpi_system_read_debug, | 300 | (void *)0); |
| 309 | (void *)0); | 301 | if (!entry) |
| 310 | if (entry) | ||
| 311 | entry->write_proc = acpi_system_write_debug; | ||
| 312 | else | ||
| 313 | goto Error; | 302 | goto Error; |
| 314 | 303 | ||
| 315 | /* 'debug_level' [R/W] */ | 304 | /* 'debug_level' [R/W] */ |
| 316 | name = ACPI_SYSTEM_FILE_DEBUG_LEVEL; | 305 | name = ACPI_SYSTEM_FILE_DEBUG_LEVEL; |
| 317 | entry = | 306 | entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, |
| 318 | create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, | 307 | acpi_root_dir, &acpi_system_debug_proc_fops, |
| 319 | acpi_root_dir, acpi_system_read_debug, | 308 | (void *)1); |
| 320 | (void *)1); | 309 | if (!entry) |
| 321 | if (entry) | ||
| 322 | entry->write_proc = acpi_system_write_debug; | ||
| 323 | else | ||
| 324 | goto Error; | 310 | goto Error; |
| 325 | 311 | ||
| 326 | Done: | 312 | Done: |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index efb959d6c8a9..3a2cfefc71ab 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
| 34 | #include <acpi/acpi_drivers.h> | 34 | #include <acpi/acpi_drivers.h> |
| 35 | 35 | ||
| 36 | #define PREFIX "ACPI: " | ||
| 37 | |||
| 36 | #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver" | 38 | #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver" |
| 37 | 39 | ||
| 38 | ACPI_MODULE_NAME("dock"); | 40 | ACPI_MODULE_NAME("dock"); |
| @@ -231,18 +233,16 @@ static int is_ata(acpi_handle handle) | |||
| 231 | static int is_battery(acpi_handle handle) | 233 | static int is_battery(acpi_handle handle) |
| 232 | { | 234 | { |
| 233 | struct acpi_device_info *info; | 235 | struct acpi_device_info *info; |
| 234 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
| 235 | int ret = 1; | 236 | int ret = 1; |
| 236 | 237 | ||
| 237 | if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) | 238 | if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) |
| 238 | return 0; | 239 | return 0; |
| 239 | info = buffer.pointer; | ||
| 240 | if (!(info->valid & ACPI_VALID_HID)) | 240 | if (!(info->valid & ACPI_VALID_HID)) |
| 241 | ret = 0; | 241 | ret = 0; |
| 242 | else | 242 | else |
| 243 | ret = !strcmp("PNP0C0A", info->hardware_id.value); | 243 | ret = !strcmp("PNP0C0A", info->hardware_id.string); |
| 244 | 244 | ||
| 245 | kfree(buffer.pointer); | 245 | kfree(info); |
| 246 | return ret; | 246 | return ret; |
| 247 | } | 247 | } |
| 248 | 248 | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 391f331674c7..f70796081c4c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -42,12 +42,12 @@ | |||
| 42 | #include <asm/io.h> | 42 | #include <asm/io.h> |
| 43 | #include <acpi/acpi_bus.h> | 43 | #include <acpi/acpi_bus.h> |
| 44 | #include <acpi/acpi_drivers.h> | 44 | #include <acpi/acpi_drivers.h> |
| 45 | #include <linux/dmi.h> | ||
| 45 | 46 | ||
| 46 | #define ACPI_EC_CLASS "embedded_controller" | 47 | #define ACPI_EC_CLASS "embedded_controller" |
| 47 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" | 48 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" |
| 48 | #define ACPI_EC_FILE_INFO "info" | 49 | #define ACPI_EC_FILE_INFO "info" |
| 49 | 50 | ||
| 50 | #undef PREFIX | ||
| 51 | #define PREFIX "ACPI: EC: " | 51 | #define PREFIX "ACPI: EC: " |
| 52 | 52 | ||
| 53 | /* EC status register */ | 53 | /* EC status register */ |
| @@ -68,15 +68,13 @@ enum ec_command { | |||
| 68 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ | 68 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ |
| 69 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 69 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
| 70 | #define ACPI_EC_CDELAY 10 /* Wait 10us before polling EC */ | 70 | #define ACPI_EC_CDELAY 10 /* Wait 10us before polling EC */ |
| 71 | #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ | ||
| 71 | 72 | ||
| 72 | #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts | 73 | #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts |
| 73 | per one transaction */ | 74 | per one transaction */ |
| 74 | 75 | ||
| 75 | enum { | 76 | enum { |
| 76 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ | 77 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
| 77 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent | ||
| 78 | * for status change */ | ||
| 79 | EC_FLAGS_NO_GPE, /* Don't use GPE mode */ | ||
| 80 | EC_FLAGS_GPE_STORM, /* GPE storm detected */ | 78 | EC_FLAGS_GPE_STORM, /* GPE storm detected */ |
| 81 | EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and | 79 | EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and |
| 82 | * OpReg are installed */ | 80 | * OpReg are installed */ |
| @@ -170,7 +168,7 @@ static void start_transaction(struct acpi_ec *ec) | |||
| 170 | acpi_ec_write_cmd(ec, ec->curr->command); | 168 | acpi_ec_write_cmd(ec, ec->curr->command); |
| 171 | } | 169 | } |
| 172 | 170 | ||
| 173 | static void gpe_transaction(struct acpi_ec *ec, u8 status) | 171 | static void advance_transaction(struct acpi_ec *ec, u8 status) |
| 174 | { | 172 | { |
| 175 | unsigned long flags; | 173 | unsigned long flags; |
| 176 | spin_lock_irqsave(&ec->curr_lock, flags); | 174 | spin_lock_irqsave(&ec->curr_lock, flags); |
| @@ -201,29 +199,6 @@ unlock: | |||
| 201 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 199 | spin_unlock_irqrestore(&ec->curr_lock, flags); |
| 202 | } | 200 | } |
| 203 | 201 | ||
| 204 | static int acpi_ec_wait(struct acpi_ec *ec) | ||
| 205 | { | ||
| 206 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), | ||
| 207 | msecs_to_jiffies(ACPI_EC_DELAY))) | ||
| 208 | return 0; | ||
| 209 | /* try restart command if we get any false interrupts */ | ||
| 210 | if (ec->curr->irq_count && | ||
| 211 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
| 212 | pr_debug(PREFIX "controller reset, restart transaction\n"); | ||
| 213 | start_transaction(ec); | ||
| 214 | if (wait_event_timeout(ec->wait, ec_transaction_done(ec), | ||
| 215 | msecs_to_jiffies(ACPI_EC_DELAY))) | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | /* missing GPEs, switch back to poll mode */ | ||
| 219 | if (printk_ratelimit()) | ||
| 220 | pr_info(PREFIX "missing confirmations, " | ||
| 221 | "switch off interrupt mode.\n"); | ||
| 222 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | ||
| 223 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
| 224 | return 1; | ||
| 225 | } | ||
| 226 | |||
| 227 | static void acpi_ec_gpe_query(void *ec_cxt); | 202 | static void acpi_ec_gpe_query(void *ec_cxt); |
| 228 | 203 | ||
| 229 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | 204 | static int ec_check_sci(struct acpi_ec *ec, u8 state) |
| @@ -236,43 +211,51 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) | |||
| 236 | return 0; | 211 | return 0; |
| 237 | } | 212 | } |
| 238 | 213 | ||
| 239 | static void ec_delay(void) | ||
| 240 | { | ||
| 241 | /* EC in MSI notebooks don't tolerate delays other than 550 usec */ | ||
| 242 | if (EC_FLAGS_MSI) | ||
| 243 | udelay(ACPI_EC_DELAY); | ||
| 244 | else | ||
| 245 | /* Use shortest sleep available */ | ||
| 246 | msleep(1); | ||
| 247 | } | ||
| 248 | |||
| 249 | static int ec_poll(struct acpi_ec *ec) | 214 | static int ec_poll(struct acpi_ec *ec) |
| 250 | { | 215 | { |
| 251 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 216 | unsigned long flags; |
| 252 | udelay(ACPI_EC_CDELAY); | 217 | int repeat = 2; /* number of command restarts */ |
| 253 | while (time_before(jiffies, delay)) { | 218 | while (repeat--) { |
| 254 | gpe_transaction(ec, acpi_ec_read_status(ec)); | 219 | unsigned long delay = jiffies + |
| 255 | ec_delay(); | 220 | msecs_to_jiffies(ACPI_EC_DELAY); |
| 256 | if (ec_transaction_done(ec)) | 221 | do { |
| 257 | return 0; | 222 | /* don't sleep with disabled interrupts */ |
| 223 | if (EC_FLAGS_MSI || irqs_disabled()) { | ||
| 224 | udelay(ACPI_EC_MSI_UDELAY); | ||
| 225 | if (ec_transaction_done(ec)) | ||
| 226 | return 0; | ||
| 227 | } else { | ||
| 228 | if (wait_event_timeout(ec->wait, | ||
| 229 | ec_transaction_done(ec), | ||
| 230 | msecs_to_jiffies(1))) | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | advance_transaction(ec, acpi_ec_read_status(ec)); | ||
| 234 | } while (time_before(jiffies, delay)); | ||
| 235 | if (!ec->curr->irq_count || | ||
| 236 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) | ||
| 237 | break; | ||
| 238 | /* try restart command if we get any false interrupts */ | ||
| 239 | pr_debug(PREFIX "controller reset, restart transaction\n"); | ||
| 240 | spin_lock_irqsave(&ec->curr_lock, flags); | ||
| 241 | start_transaction(ec); | ||
| 242 | spin_unlock_irqrestore(&ec->curr_lock, flags); | ||
| 258 | } | 243 | } |
| 259 | return -ETIME; | 244 | return -ETIME; |
| 260 | } | 245 | } |
| 261 | 246 | ||
| 262 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | 247 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, |
| 263 | struct transaction *t, | 248 | struct transaction *t) |
| 264 | int force_poll) | ||
| 265 | { | 249 | { |
| 266 | unsigned long tmp; | 250 | unsigned long tmp; |
| 267 | int ret = 0; | 251 | int ret = 0; |
| 268 | pr_debug(PREFIX "transaction start\n"); | 252 | pr_debug(PREFIX "transaction start\n"); |
| 269 | /* disable GPE during transaction if storm is detected */ | 253 | /* disable GPE during transaction if storm is detected */ |
| 270 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | 254 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
| 271 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
| 272 | acpi_disable_gpe(NULL, ec->gpe); | 255 | acpi_disable_gpe(NULL, ec->gpe); |
| 273 | } | 256 | } |
| 274 | if (EC_FLAGS_MSI) | 257 | if (EC_FLAGS_MSI) |
| 275 | udelay(ACPI_EC_DELAY); | 258 | udelay(ACPI_EC_MSI_UDELAY); |
| 276 | /* start transaction */ | 259 | /* start transaction */ |
| 277 | spin_lock_irqsave(&ec->curr_lock, tmp); | 260 | spin_lock_irqsave(&ec->curr_lock, tmp); |
| 278 | /* following two actions should be kept atomic */ | 261 | /* following two actions should be kept atomic */ |
| @@ -281,11 +264,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 281 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) | 264 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) |
| 282 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 265 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
| 283 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 266 | spin_unlock_irqrestore(&ec->curr_lock, tmp); |
| 284 | /* if we selected poll mode or failed in GPE-mode do a poll loop */ | 267 | ret = ec_poll(ec); |
| 285 | if (force_poll || | ||
| 286 | !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || | ||
| 287 | acpi_ec_wait(ec)) | ||
| 288 | ret = ec_poll(ec); | ||
| 289 | pr_debug(PREFIX "transaction end\n"); | 268 | pr_debug(PREFIX "transaction end\n"); |
| 290 | spin_lock_irqsave(&ec->curr_lock, tmp); | 269 | spin_lock_irqsave(&ec->curr_lock, tmp); |
| 291 | ec->curr = NULL; | 270 | ec->curr = NULL; |
| @@ -295,8 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 295 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 274 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
| 296 | /* it is safe to enable GPE outside of transaction */ | 275 | /* it is safe to enable GPE outside of transaction */ |
| 297 | acpi_enable_gpe(NULL, ec->gpe); | 276 | acpi_enable_gpe(NULL, ec->gpe); |
| 298 | } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 277 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { |
| 299 | t->irq_count > ACPI_EC_STORM_THRESHOLD) { | ||
| 300 | pr_info(PREFIX "GPE storm detected, " | 278 | pr_info(PREFIX "GPE storm detected, " |
| 301 | "transactions will use polling mode\n"); | 279 | "transactions will use polling mode\n"); |
| 302 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | 280 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); |
| @@ -314,16 +292,14 @@ static int ec_wait_ibf0(struct acpi_ec *ec) | |||
| 314 | { | 292 | { |
| 315 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 293 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
| 316 | /* interrupt wait manually if GPE mode is not active */ | 294 | /* interrupt wait manually if GPE mode is not active */ |
| 317 | unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ? | ||
| 318 | msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1); | ||
| 319 | while (time_before(jiffies, delay)) | 295 | while (time_before(jiffies, delay)) |
| 320 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout)) | 296 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), |
| 297 | msecs_to_jiffies(1))) | ||
| 321 | return 0; | 298 | return 0; |
| 322 | return -ETIME; | 299 | return -ETIME; |
| 323 | } | 300 | } |
| 324 | 301 | ||
| 325 | static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, | 302 | static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) |
| 326 | int force_poll) | ||
| 327 | { | 303 | { |
| 328 | int status; | 304 | int status; |
| 329 | u32 glk; | 305 | u32 glk; |
| @@ -345,7 +321,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, | |||
| 345 | status = -ETIME; | 321 | status = -ETIME; |
| 346 | goto end; | 322 | goto end; |
| 347 | } | 323 | } |
| 348 | status = acpi_ec_transaction_unlocked(ec, t, force_poll); | 324 | status = acpi_ec_transaction_unlocked(ec, t); |
| 349 | end: | 325 | end: |
| 350 | if (ec->global_lock) | 326 | if (ec->global_lock) |
| 351 | acpi_release_global_lock(glk); | 327 | acpi_release_global_lock(glk); |
| @@ -354,10 +330,6 @@ unlock: | |||
| 354 | return status; | 330 | return status; |
| 355 | } | 331 | } |
| 356 | 332 | ||
| 357 | /* | ||
| 358 | * Note: samsung nv5000 doesn't work with ec burst mode. | ||
| 359 | * http://bugzilla.kernel.org/show_bug.cgi?id=4980 | ||
| 360 | */ | ||
| 361 | static int acpi_ec_burst_enable(struct acpi_ec *ec) | 333 | static int acpi_ec_burst_enable(struct acpi_ec *ec) |
| 362 | { | 334 | { |
| 363 | u8 d; | 335 | u8 d; |
| @@ -365,7 +337,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec) | |||
| 365 | .wdata = NULL, .rdata = &d, | 337 | .wdata = NULL, .rdata = &d, |
| 366 | .wlen = 0, .rlen = 1}; | 338 | .wlen = 0, .rlen = 1}; |
| 367 | 339 | ||
| 368 | return acpi_ec_transaction(ec, &t, 0); | 340 | return acpi_ec_transaction(ec, &t); |
| 369 | } | 341 | } |
| 370 | 342 | ||
| 371 | static int acpi_ec_burst_disable(struct acpi_ec *ec) | 343 | static int acpi_ec_burst_disable(struct acpi_ec *ec) |
| @@ -375,7 +347,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec) | |||
| 375 | .wlen = 0, .rlen = 0}; | 347 | .wlen = 0, .rlen = 0}; |
| 376 | 348 | ||
| 377 | return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? | 349 | return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? |
| 378 | acpi_ec_transaction(ec, &t, 0) : 0; | 350 | acpi_ec_transaction(ec, &t) : 0; |
| 379 | } | 351 | } |
| 380 | 352 | ||
| 381 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) | 353 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) |
| @@ -386,7 +358,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) | |||
| 386 | .wdata = &address, .rdata = &d, | 358 | .wdata = &address, .rdata = &d, |
| 387 | .wlen = 1, .rlen = 1}; | 359 | .wlen = 1, .rlen = 1}; |
| 388 | 360 | ||
| 389 | result = acpi_ec_transaction(ec, &t, 0); | 361 | result = acpi_ec_transaction(ec, &t); |
| 390 | *data = d; | 362 | *data = d; |
| 391 | return result; | 363 | return result; |
| 392 | } | 364 | } |
| @@ -398,7 +370,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) | |||
| 398 | .wdata = wdata, .rdata = NULL, | 370 | .wdata = wdata, .rdata = NULL, |
| 399 | .wlen = 2, .rlen = 0}; | 371 | .wlen = 2, .rlen = 0}; |
| 400 | 372 | ||
| 401 | return acpi_ec_transaction(ec, &t, 0); | 373 | return acpi_ec_transaction(ec, &t); |
| 402 | } | 374 | } |
| 403 | 375 | ||
| 404 | /* | 376 | /* |
| @@ -466,7 +438,7 @@ int ec_transaction(u8 command, | |||
| 466 | if (!first_ec) | 438 | if (!first_ec) |
| 467 | return -ENODEV; | 439 | return -ENODEV; |
| 468 | 440 | ||
| 469 | return acpi_ec_transaction(first_ec, &t, force_poll); | 441 | return acpi_ec_transaction(first_ec, &t); |
| 470 | } | 442 | } |
| 471 | 443 | ||
| 472 | EXPORT_SYMBOL(ec_transaction); | 444 | EXPORT_SYMBOL(ec_transaction); |
| @@ -487,7 +459,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | |||
| 487 | * bit to be cleared (and thus clearing the interrupt source). | 459 | * bit to be cleared (and thus clearing the interrupt source). |
| 488 | */ | 460 | */ |
| 489 | 461 | ||
| 490 | result = acpi_ec_transaction(ec, &t, 0); | 462 | result = acpi_ec_transaction(ec, &t); |
| 491 | if (result) | 463 | if (result) |
| 492 | return result; | 464 | return result; |
| 493 | 465 | ||
| @@ -570,28 +542,10 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 570 | pr_debug(PREFIX "~~~> interrupt\n"); | 542 | pr_debug(PREFIX "~~~> interrupt\n"); |
| 571 | status = acpi_ec_read_status(ec); | 543 | status = acpi_ec_read_status(ec); |
| 572 | 544 | ||
| 573 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) { | 545 | advance_transaction(ec, status); |
| 574 | gpe_transaction(ec, status); | 546 | if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) |
| 575 | if (ec_transaction_done(ec) && | 547 | wake_up(&ec->wait); |
| 576 | (status & ACPI_EC_FLAG_IBF) == 0) | ||
| 577 | wake_up(&ec->wait); | ||
| 578 | } | ||
| 579 | |||
| 580 | ec_check_sci(ec, status); | 548 | ec_check_sci(ec, status); |
| 581 | if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | ||
| 582 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { | ||
| 583 | /* this is non-query, must be confirmation */ | ||
| 584 | if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
| 585 | if (printk_ratelimit()) | ||
| 586 | pr_info(PREFIX "non-query interrupt received," | ||
| 587 | " switching to interrupt mode\n"); | ||
| 588 | } else { | ||
| 589 | /* hush, STORM switches the mode every transaction */ | ||
| 590 | pr_debug(PREFIX "non-query interrupt received," | ||
| 591 | " switching to interrupt mode\n"); | ||
| 592 | } | ||
| 593 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
| 594 | } | ||
| 595 | return ACPI_INTERRUPT_HANDLED; | 549 | return ACPI_INTERRUPT_HANDLED; |
| 596 | } | 550 | } |
| 597 | 551 | ||
| @@ -617,7 +571,8 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
| 617 | if (bits != 8 && acpi_strict) | 571 | if (bits != 8 && acpi_strict) |
| 618 | return AE_BAD_PARAMETER; | 572 | return AE_BAD_PARAMETER; |
| 619 | 573 | ||
| 620 | acpi_ec_burst_enable(ec); | 574 | if (EC_FLAGS_MSI) |
| 575 | acpi_ec_burst_enable(ec); | ||
| 621 | 576 | ||
| 622 | if (function == ACPI_READ) { | 577 | if (function == ACPI_READ) { |
| 623 | result = acpi_ec_read(ec, address, &temp); | 578 | result = acpi_ec_read(ec, address, &temp); |
| @@ -638,7 +593,8 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, | |||
| 638 | } | 593 | } |
| 639 | } | 594 | } |
| 640 | 595 | ||
| 641 | acpi_ec_burst_disable(ec); | 596 | if (EC_FLAGS_MSI) |
| 597 | acpi_ec_burst_disable(ec); | ||
| 642 | 598 | ||
| 643 | switch (result) { | 599 | switch (result) { |
| 644 | case -EINVAL: | 600 | case -EINVAL: |
| @@ -788,6 +744,42 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | |||
| 788 | return AE_CTRL_TERMINATE; | 744 | return AE_CTRL_TERMINATE; |
| 789 | } | 745 | } |
| 790 | 746 | ||
| 747 | static int ec_install_handlers(struct acpi_ec *ec) | ||
| 748 | { | ||
| 749 | acpi_status status; | ||
| 750 | if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) | ||
| 751 | return 0; | ||
| 752 | status = acpi_install_gpe_handler(NULL, ec->gpe, | ||
| 753 | ACPI_GPE_EDGE_TRIGGERED, | ||
| 754 | &acpi_ec_gpe_handler, ec); | ||
| 755 | if (ACPI_FAILURE(status)) | ||
| 756 | return -ENODEV; | ||
| 757 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | ||
| 758 | acpi_enable_gpe(NULL, ec->gpe); | ||
| 759 | status = acpi_install_address_space_handler(ec->handle, | ||
| 760 | ACPI_ADR_SPACE_EC, | ||
| 761 | &acpi_ec_space_handler, | ||
| 762 | NULL, ec); | ||
| 763 | if (ACPI_FAILURE(status)) { | ||
| 764 | if (status == AE_NOT_FOUND) { | ||
| 765 | /* | ||
| 766 | * Maybe OS fails in evaluating the _REG object. | ||
| 767 | * The AE_NOT_FOUND error will be ignored and OS | ||
| 768 | * continue to initialize EC. | ||
| 769 | */ | ||
| 770 | printk(KERN_ERR "Fail in evaluating the _REG object" | ||
| 771 | " of EC device. Broken bios is suspected.\n"); | ||
| 772 | } else { | ||
| 773 | acpi_remove_gpe_handler(NULL, ec->gpe, | ||
| 774 | &acpi_ec_gpe_handler); | ||
| 775 | return -ENODEV; | ||
| 776 | } | ||
| 777 | } | ||
| 778 | |||
| 779 | set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); | ||
| 780 | return 0; | ||
| 781 | } | ||
| 782 | |||
| 791 | static void ec_remove_handlers(struct acpi_ec *ec) | 783 | static void ec_remove_handlers(struct acpi_ec *ec) |
| 792 | { | 784 | { |
| 793 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, | 785 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, |
| @@ -802,9 +794,8 @@ static void ec_remove_handlers(struct acpi_ec *ec) | |||
| 802 | static int acpi_ec_add(struct acpi_device *device) | 794 | static int acpi_ec_add(struct acpi_device *device) |
| 803 | { | 795 | { |
| 804 | struct acpi_ec *ec = NULL; | 796 | struct acpi_ec *ec = NULL; |
| 797 | int ret; | ||
| 805 | 798 | ||
| 806 | if (!device) | ||
| 807 | return -EINVAL; | ||
| 808 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | 799 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |
| 809 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | 800 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
| 810 | 801 | ||
| @@ -837,9 +828,12 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 837 | acpi_ec_add_fs(device); | 828 | acpi_ec_add_fs(device); |
| 838 | pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", | 829 | pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", |
| 839 | ec->gpe, ec->command_addr, ec->data_addr); | 830 | ec->gpe, ec->command_addr, ec->data_addr); |
| 840 | pr_info(PREFIX "driver started in %s mode\n", | 831 | |
| 841 | (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); | 832 | ret = ec_install_handlers(ec); |
| 842 | return 0; | 833 | |
| 834 | /* EC is fully operational, allow queries */ | ||
| 835 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | ||
| 836 | return ret; | ||
| 843 | } | 837 | } |
| 844 | 838 | ||
| 845 | static int acpi_ec_remove(struct acpi_device *device, int type) | 839 | static int acpi_ec_remove(struct acpi_device *device, int type) |
| @@ -851,6 +845,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type) | |||
| 851 | return -EINVAL; | 845 | return -EINVAL; |
| 852 | 846 | ||
| 853 | ec = acpi_driver_data(device); | 847 | ec = acpi_driver_data(device); |
| 848 | ec_remove_handlers(ec); | ||
| 854 | mutex_lock(&ec->lock); | 849 | mutex_lock(&ec->lock); |
| 855 | list_for_each_entry_safe(handler, tmp, &ec->list, node) { | 850 | list_for_each_entry_safe(handler, tmp, &ec->list, node) { |
| 856 | list_del(&handler->node); | 851 | list_del(&handler->node); |
| @@ -888,75 +883,6 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) | |||
| 888 | return AE_OK; | 883 | return AE_OK; |
| 889 | } | 884 | } |
| 890 | 885 | ||
| 891 | static int ec_install_handlers(struct acpi_ec *ec) | ||
| 892 | { | ||
| 893 | acpi_status status; | ||
| 894 | if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) | ||
| 895 | return 0; | ||
| 896 | status = acpi_install_gpe_handler(NULL, ec->gpe, | ||
| 897 | ACPI_GPE_EDGE_TRIGGERED, | ||
| 898 | &acpi_ec_gpe_handler, ec); | ||
| 899 | if (ACPI_FAILURE(status)) | ||
| 900 | return -ENODEV; | ||
| 901 | acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); | ||
| 902 | acpi_enable_gpe(NULL, ec->gpe); | ||
| 903 | status = acpi_install_address_space_handler(ec->handle, | ||
| 904 | ACPI_ADR_SPACE_EC, | ||
| 905 | &acpi_ec_space_handler, | ||
| 906 | NULL, ec); | ||
| 907 | if (ACPI_FAILURE(status)) { | ||
| 908 | if (status == AE_NOT_FOUND) { | ||
| 909 | /* | ||
| 910 | * Maybe OS fails in evaluating the _REG object. | ||
| 911 | * The AE_NOT_FOUND error will be ignored and OS | ||
| 912 | * continue to initialize EC. | ||
| 913 | */ | ||
| 914 | printk(KERN_ERR "Fail in evaluating the _REG object" | ||
| 915 | " of EC device. Broken bios is suspected.\n"); | ||
| 916 | } else { | ||
| 917 | acpi_remove_gpe_handler(NULL, ec->gpe, | ||
| 918 | &acpi_ec_gpe_handler); | ||
| 919 | return -ENODEV; | ||
| 920 | } | ||
| 921 | } | ||
| 922 | |||
| 923 | set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); | ||
| 924 | return 0; | ||
| 925 | } | ||
| 926 | |||
| 927 | static int acpi_ec_start(struct acpi_device *device) | ||
| 928 | { | ||
| 929 | struct acpi_ec *ec; | ||
| 930 | int ret = 0; | ||
| 931 | |||
| 932 | if (!device) | ||
| 933 | return -EINVAL; | ||
| 934 | |||
| 935 | ec = acpi_driver_data(device); | ||
| 936 | |||
| 937 | if (!ec) | ||
| 938 | return -EINVAL; | ||
| 939 | |||
| 940 | ret = ec_install_handlers(ec); | ||
| 941 | |||
| 942 | /* EC is fully operational, allow queries */ | ||
| 943 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | ||
| 944 | return ret; | ||
| 945 | } | ||
| 946 | |||
| 947 | static int acpi_ec_stop(struct acpi_device *device, int type) | ||
| 948 | { | ||
| 949 | struct acpi_ec *ec; | ||
| 950 | if (!device) | ||
| 951 | return -EINVAL; | ||
| 952 | ec = acpi_driver_data(device); | ||
| 953 | if (!ec) | ||
| 954 | return -EINVAL; | ||
| 955 | ec_remove_handlers(ec); | ||
| 956 | |||
| 957 | return 0; | ||
| 958 | } | ||
| 959 | |||
| 960 | int __init acpi_boot_ec_enable(void) | 886 | int __init acpi_boot_ec_enable(void) |
| 961 | { | 887 | { |
| 962 | if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) | 888 | if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) |
| @@ -1054,8 +980,6 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) | |||
| 1054 | { | 980 | { |
| 1055 | struct acpi_ec *ec = acpi_driver_data(device); | 981 | struct acpi_ec *ec = acpi_driver_data(device); |
| 1056 | /* Stop using GPE */ | 982 | /* Stop using GPE */ |
| 1057 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | ||
| 1058 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
| 1059 | acpi_disable_gpe(NULL, ec->gpe); | 983 | acpi_disable_gpe(NULL, ec->gpe); |
| 1060 | return 0; | 984 | return 0; |
| 1061 | } | 985 | } |
| @@ -1064,8 +988,6 @@ static int acpi_ec_resume(struct acpi_device *device) | |||
| 1064 | { | 988 | { |
| 1065 | struct acpi_ec *ec = acpi_driver_data(device); | 989 | struct acpi_ec *ec = acpi_driver_data(device); |
| 1066 | /* Enable use of GPE back */ | 990 | /* Enable use of GPE back */ |
| 1067 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); | ||
| 1068 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
| 1069 | acpi_enable_gpe(NULL, ec->gpe); | 991 | acpi_enable_gpe(NULL, ec->gpe); |
| 1070 | return 0; | 992 | return 0; |
| 1071 | } | 993 | } |
| @@ -1077,8 +999,6 @@ static struct acpi_driver acpi_ec_driver = { | |||
| 1077 | .ops = { | 999 | .ops = { |
| 1078 | .add = acpi_ec_add, | 1000 | .add = acpi_ec_add, |
| 1079 | .remove = acpi_ec_remove, | 1001 | .remove = acpi_ec_remove, |
| 1080 | .start = acpi_ec_start, | ||
| 1081 | .stop = acpi_ec_stop, | ||
| 1082 | .suspend = acpi_ec_suspend, | 1002 | .suspend = acpi_ec_suspend, |
| 1083 | .resume = acpi_ec_resume, | 1003 | .resume = acpi_ec_resume, |
| 1084 | }, | 1004 | }, |
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index aeb7e5fb4a04..c511071bfd79 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <net/netlink.h> | 14 | #include <net/netlink.h> |
| 15 | #include <net/genetlink.h> | 15 | #include <net/genetlink.h> |
| 16 | 16 | ||
| 17 | #include "internal.h" | ||
| 18 | |||
| 17 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 19 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
| 18 | ACPI_MODULE_NAME("event"); | 20 | ACPI_MODULE_NAME("event"); |
| 19 | 21 | ||
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 53698ea08371..f419849a0d3f 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
| 35 | #include <acpi/acpi_drivers.h> | 35 | #include <acpi/acpi_drivers.h> |
| 36 | 36 | ||
| 37 | #define PREFIX "ACPI: " | ||
| 38 | |||
| 37 | #define ACPI_FAN_CLASS "fan" | 39 | #define ACPI_FAN_CLASS "fan" |
| 38 | #define ACPI_FAN_FILE_STATE "state" | 40 | #define ACPI_FAN_FILE_STATE "state" |
| 39 | 41 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index a8a5c29958c8..c6645f26224b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include <linux/rwsem.h> | 12 | #include <linux/rwsem.h> |
| 13 | #include <linux/acpi.h> | 13 | #include <linux/acpi.h> |
| 14 | 14 | ||
| 15 | #include "internal.h" | ||
| 16 | |||
| 15 | #define ACPI_GLUE_DEBUG 0 | 17 | #define ACPI_GLUE_DEBUG 0 |
| 16 | #if ACPI_GLUE_DEBUG | 18 | #if ACPI_GLUE_DEBUG |
| 17 | #define DBG(x...) printk(PREFIX x) | 19 | #define DBG(x...) printk(PREFIX x) |
| @@ -93,15 +95,13 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 93 | { | 95 | { |
| 94 | acpi_status status; | 96 | acpi_status status; |
| 95 | struct acpi_device_info *info; | 97 | struct acpi_device_info *info; |
| 96 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 97 | struct acpi_find_child *find = context; | 98 | struct acpi_find_child *find = context; |
| 98 | 99 | ||
| 99 | status = acpi_get_object_info(handle, &buffer); | 100 | status = acpi_get_object_info(handle, &info); |
| 100 | if (ACPI_SUCCESS(status)) { | 101 | if (ACPI_SUCCESS(status)) { |
| 101 | info = buffer.pointer; | ||
| 102 | if (info->address == find->address) | 102 | if (info->address == find->address) |
| 103 | find->handle = handle; | 103 | find->handle = handle; |
| 104 | kfree(buffer.pointer); | 104 | kfree(info); |
| 105 | } | 105 | } |
| 106 | return AE_OK; | 106 | return AE_OK; |
| 107 | } | 107 | } |
| @@ -121,7 +121,7 @@ EXPORT_SYMBOL(acpi_get_child); | |||
| 121 | 121 | ||
| 122 | /* Link ACPI devices with physical devices */ | 122 | /* Link ACPI devices with physical devices */ |
| 123 | static void acpi_glue_data_handler(acpi_handle handle, | 123 | static void acpi_glue_data_handler(acpi_handle handle, |
| 124 | u32 function, void *context) | 124 | void *context) |
| 125 | { | 125 | { |
| 126 | /* we provide an empty handler */ | 126 | /* we provide an empty handler */ |
| 127 | } | 127 | } |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 11a69b53004e..074cf8682d52 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
| @@ -1,4 +1,24 @@ | |||
| 1 | /* For use by Linux/ACPI infrastructure, not drivers */ | 1 | /* |
| 2 | * acpi/internal.h | ||
| 3 | * For use by Linux/ACPI infrastructure, not drivers | ||
| 4 | * | ||
| 5 | * Copyright (c) 2009, Intel Corporation. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms and conditions of the GNU General Public License, | ||
| 9 | * version 2, as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along with | ||
| 17 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #define PREFIX "ACPI: " | ||
| 2 | 22 | ||
| 3 | int init_acpi_device_notify(void); | 23 | int init_acpi_device_notify(void); |
| 4 | int acpi_scan_init(void); | 24 | int acpi_scan_init(void); |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index d440ccd27d91..202dd0c976a3 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
| 31 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> |
| 32 | 32 | ||
| 33 | #define PREFIX "ACPI: " | ||
| 34 | |||
| 33 | #define ACPI_NUMA 0x80000000 | 35 | #define ACPI_NUMA 0x80000000 |
| 34 | #define _COMPONENT ACPI_NUMA | 36 | #define _COMPONENT ACPI_NUMA |
| 35 | ACPI_MODULE_NAME("numa"); | 37 | ACPI_MODULE_NAME("numa"); |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 5691f165a952..56071b67bed5 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -58,6 +58,7 @@ struct acpi_os_dpc { | |||
| 58 | acpi_osd_exec_callback function; | 58 | acpi_osd_exec_callback function; |
| 59 | void *context; | 59 | void *context; |
| 60 | struct work_struct work; | 60 | struct work_struct work; |
| 61 | int wait; | ||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | #ifdef CONFIG_ACPI_CUSTOM_DSDT | 64 | #ifdef CONFIG_ACPI_CUSTOM_DSDT |
| @@ -88,6 +89,7 @@ struct acpi_res_list { | |||
| 88 | char name[5]; /* only can have a length of 4 chars, make use of this | 89 | char name[5]; /* only can have a length of 4 chars, make use of this |
| 89 | one instead of res->name, no need to kalloc then */ | 90 | one instead of res->name, no need to kalloc then */ |
| 90 | struct list_head resource_list; | 91 | struct list_head resource_list; |
| 92 | int count; | ||
| 91 | }; | 93 | }; |
| 92 | 94 | ||
| 93 | static LIST_HEAD(resource_list_head); | 95 | static LIST_HEAD(resource_list_head); |
| @@ -697,31 +699,12 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ | |||
| 697 | static void acpi_os_execute_deferred(struct work_struct *work) | 699 | static void acpi_os_execute_deferred(struct work_struct *work) |
| 698 | { | 700 | { |
| 699 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | 701 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); |
| 700 | if (!dpc) { | ||
| 701 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); | ||
| 702 | return; | ||
| 703 | } | ||
| 704 | |||
| 705 | dpc->function(dpc->context); | ||
| 706 | kfree(dpc); | ||
| 707 | |||
| 708 | return; | ||
| 709 | } | ||
| 710 | |||
| 711 | static void acpi_os_execute_hp_deferred(struct work_struct *work) | ||
| 712 | { | ||
| 713 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | ||
| 714 | if (!dpc) { | ||
| 715 | printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); | ||
| 716 | return; | ||
| 717 | } | ||
| 718 | 702 | ||
| 719 | acpi_os_wait_events_complete(NULL); | 703 | if (dpc->wait) |
| 704 | acpi_os_wait_events_complete(NULL); | ||
| 720 | 705 | ||
| 721 | dpc->function(dpc->context); | 706 | dpc->function(dpc->context); |
| 722 | kfree(dpc); | 707 | kfree(dpc); |
| 723 | |||
| 724 | return; | ||
| 725 | } | 708 | } |
| 726 | 709 | ||
| 727 | /******************************************************************************* | 710 | /******************************************************************************* |
| @@ -745,15 +728,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 745 | acpi_status status = AE_OK; | 728 | acpi_status status = AE_OK; |
| 746 | struct acpi_os_dpc *dpc; | 729 | struct acpi_os_dpc *dpc; |
| 747 | struct workqueue_struct *queue; | 730 | struct workqueue_struct *queue; |
| 748 | work_func_t func; | ||
| 749 | int ret; | 731 | int ret; |
| 750 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 732 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
| 751 | "Scheduling function [%p(%p)] for deferred execution.\n", | 733 | "Scheduling function [%p(%p)] for deferred execution.\n", |
| 752 | function, context)); | 734 | function, context)); |
| 753 | 735 | ||
| 754 | if (!function) | ||
| 755 | return AE_BAD_PARAMETER; | ||
| 756 | |||
| 757 | /* | 736 | /* |
| 758 | * Allocate/initialize DPC structure. Note that this memory will be | 737 | * Allocate/initialize DPC structure. Note that this memory will be |
| 759 | * freed by the callee. The kernel handles the work_struct list in a | 738 | * freed by the callee. The kernel handles the work_struct list in a |
| @@ -778,8 +757,8 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, | |||
| 778 | */ | 757 | */ |
| 779 | queue = hp ? kacpi_hotplug_wq : | 758 | queue = hp ? kacpi_hotplug_wq : |
| 780 | (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); | 759 | (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); |
| 781 | func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; | 760 | dpc->wait = hp ? 1 : 0; |
| 782 | INIT_WORK(&dpc->work, func); | 761 | INIT_WORK(&dpc->work, acpi_os_execute_deferred); |
| 783 | ret = queue_work(queue, &dpc->work); | 762 | ret = queue_work(queue, &dpc->work); |
| 784 | 763 | ||
| 785 | if (!ret) { | 764 | if (!ret) { |
| @@ -1358,6 +1337,89 @@ acpi_os_validate_interface (char *interface) | |||
| 1358 | return AE_SUPPORT; | 1337 | return AE_SUPPORT; |
| 1359 | } | 1338 | } |
| 1360 | 1339 | ||
| 1340 | static inline int acpi_res_list_add(struct acpi_res_list *res) | ||
| 1341 | { | ||
| 1342 | struct acpi_res_list *res_list_elem; | ||
| 1343 | |||
| 1344 | list_for_each_entry(res_list_elem, &resource_list_head, | ||
| 1345 | resource_list) { | ||
| 1346 | |||
| 1347 | if (res->resource_type == res_list_elem->resource_type && | ||
| 1348 | res->start == res_list_elem->start && | ||
| 1349 | res->end == res_list_elem->end) { | ||
| 1350 | |||
| 1351 | /* | ||
| 1352 | * The Region(addr,len) already exist in the list, | ||
| 1353 | * just increase the count | ||
| 1354 | */ | ||
| 1355 | |||
| 1356 | res_list_elem->count++; | ||
| 1357 | return 0; | ||
| 1358 | } | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | res->count = 1; | ||
| 1362 | list_add(&res->resource_list, &resource_list_head); | ||
| 1363 | return 1; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | static inline void acpi_res_list_del(struct acpi_res_list *res) | ||
| 1367 | { | ||
| 1368 | struct acpi_res_list *res_list_elem; | ||
| 1369 | |||
| 1370 | list_for_each_entry(res_list_elem, &resource_list_head, | ||
| 1371 | resource_list) { | ||
| 1372 | |||
| 1373 | if (res->resource_type == res_list_elem->resource_type && | ||
| 1374 | res->start == res_list_elem->start && | ||
| 1375 | res->end == res_list_elem->end) { | ||
| 1376 | |||
| 1377 | /* | ||
| 1378 | * If the res count is decreased to 0, | ||
| 1379 | * remove and free it | ||
| 1380 | */ | ||
| 1381 | |||
| 1382 | if (--res_list_elem->count == 0) { | ||
| 1383 | list_del(&res_list_elem->resource_list); | ||
| 1384 | kfree(res_list_elem); | ||
| 1385 | } | ||
| 1386 | return; | ||
| 1387 | } | ||
| 1388 | } | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | acpi_status | ||
| 1392 | acpi_os_invalidate_address( | ||
| 1393 | u8 space_id, | ||
| 1394 | acpi_physical_address address, | ||
| 1395 | acpi_size length) | ||
| 1396 | { | ||
| 1397 | struct acpi_res_list res; | ||
| 1398 | |||
| 1399 | switch (space_id) { | ||
| 1400 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
| 1401 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | ||
| 1402 | /* Only interference checks against SystemIO and SytemMemory | ||
| 1403 | are needed */ | ||
| 1404 | res.start = address; | ||
| 1405 | res.end = address + length - 1; | ||
| 1406 | res.resource_type = space_id; | ||
| 1407 | spin_lock(&acpi_res_lock); | ||
| 1408 | acpi_res_list_del(&res); | ||
| 1409 | spin_unlock(&acpi_res_lock); | ||
| 1410 | break; | ||
| 1411 | case ACPI_ADR_SPACE_PCI_CONFIG: | ||
| 1412 | case ACPI_ADR_SPACE_EC: | ||
| 1413 | case ACPI_ADR_SPACE_SMBUS: | ||
| 1414 | case ACPI_ADR_SPACE_CMOS: | ||
| 1415 | case ACPI_ADR_SPACE_PCI_BAR_TARGET: | ||
| 1416 | case ACPI_ADR_SPACE_DATA_TABLE: | ||
| 1417 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | ||
| 1418 | break; | ||
| 1419 | } | ||
| 1420 | return AE_OK; | ||
| 1421 | } | ||
| 1422 | |||
| 1361 | /****************************************************************************** | 1423 | /****************************************************************************** |
| 1362 | * | 1424 | * |
| 1363 | * FUNCTION: acpi_os_validate_address | 1425 | * FUNCTION: acpi_os_validate_address |
| @@ -1382,6 +1444,7 @@ acpi_os_validate_address ( | |||
| 1382 | char *name) | 1444 | char *name) |
| 1383 | { | 1445 | { |
| 1384 | struct acpi_res_list *res; | 1446 | struct acpi_res_list *res; |
| 1447 | int added; | ||
| 1385 | if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) | 1448 | if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) |
| 1386 | return AE_OK; | 1449 | return AE_OK; |
| 1387 | 1450 | ||
| @@ -1399,14 +1462,17 @@ acpi_os_validate_address ( | |||
| 1399 | res->end = address + length - 1; | 1462 | res->end = address + length - 1; |
| 1400 | res->resource_type = space_id; | 1463 | res->resource_type = space_id; |
| 1401 | spin_lock(&acpi_res_lock); | 1464 | spin_lock(&acpi_res_lock); |
| 1402 | list_add(&res->resource_list, &resource_list_head); | 1465 | added = acpi_res_list_add(res); |
| 1403 | spin_unlock(&acpi_res_lock); | 1466 | spin_unlock(&acpi_res_lock); |
| 1404 | pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, " | 1467 | pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, " |
| 1405 | "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO) | 1468 | "name: %s\n", added ? "Added" : "Already exist", |
| 1469 | (space_id == ACPI_ADR_SPACE_SYSTEM_IO) | ||
| 1406 | ? "SystemIO" : "System Memory", | 1470 | ? "SystemIO" : "System Memory", |
| 1407 | (unsigned long long)res->start, | 1471 | (unsigned long long)res->start, |
| 1408 | (unsigned long long)res->end, | 1472 | (unsigned long long)res->end, |
| 1409 | res->name); | 1473 | res->name); |
| 1474 | if (!added) | ||
| 1475 | kfree(res); | ||
| 1410 | break; | 1476 | break; |
| 1411 | case ACPI_ADR_SPACE_PCI_CONFIG: | 1477 | case ACPI_ADR_SPACE_PCI_CONFIG: |
| 1412 | case ACPI_ADR_SPACE_EC: | 1478 | case ACPI_ADR_SPACE_EC: |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b794eb88ab90..843699ed93f2 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #include <acpi/acpi_bus.h> | 40 | #include <acpi/acpi_bus.h> |
| 41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
| 42 | 42 | ||
| 43 | #define PREFIX "ACPI: " | ||
| 44 | |||
| 43 | #define _COMPONENT ACPI_PCI_COMPONENT | 45 | #define _COMPONENT ACPI_PCI_COMPONENT |
| 44 | ACPI_MODULE_NAME("pci_irq"); | 46 | ACPI_MODULE_NAME("pci_irq"); |
| 45 | 47 | ||
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 16e0f9d3d17c..394ae89409c2 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -43,6 +43,8 @@ | |||
| 43 | #include <acpi/acpi_bus.h> | 43 | #include <acpi/acpi_bus.h> |
| 44 | #include <acpi/acpi_drivers.h> | 44 | #include <acpi/acpi_drivers.h> |
| 45 | 45 | ||
| 46 | #define PREFIX "ACPI: " | ||
| 47 | |||
| 46 | #define _COMPONENT ACPI_PCI_COMPONENT | 48 | #define _COMPONENT ACPI_PCI_COMPONENT |
| 47 | ACPI_MODULE_NAME("pci_link"); | 49 | ACPI_MODULE_NAME("pci_link"); |
| 48 | #define ACPI_PCI_LINK_CLASS "pci_irq_routing" | 50 | #define ACPI_PCI_LINK_CLASS "pci_irq_routing" |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 31b961c2f22f..31122214e0ec 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | #include <acpi/acpi_bus.h> | 36 | #include <acpi/acpi_bus.h> |
| 37 | #include <acpi/acpi_drivers.h> | 37 | #include <acpi/acpi_drivers.h> |
| 38 | 38 | ||
| 39 | #define PREFIX "ACPI: " | ||
| 40 | |||
| 39 | #define _COMPONENT ACPI_PCI_COMPONENT | 41 | #define _COMPONENT ACPI_PCI_COMPONENT |
| 40 | ACPI_MODULE_NAME("pci_root"); | 42 | ACPI_MODULE_NAME("pci_root"); |
| 41 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" | 43 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" |
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index 12158e0d009b..45da2bae36c8 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
| 32 | #include <acpi/acpi_bus.h> | 32 | #include <acpi/acpi_bus.h> |
| 33 | #include <acpi/acpi_drivers.h> | 33 | #include <acpi/acpi_drivers.h> |
| 34 | #include <linux/dmi.h> | ||
| 34 | 35 | ||
| 35 | static int debug; | 36 | static int debug; |
| 36 | static int check_sta_before_sun; | 37 | static int check_sta_before_sun; |
| @@ -57,7 +58,7 @@ ACPI_MODULE_NAME("pci_slot"); | |||
| 57 | MY_NAME , ## arg); \ | 58 | MY_NAME , ## arg); \ |
| 58 | } while (0) | 59 | } while (0) |
| 59 | 60 | ||
| 60 | #define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */ | 61 | #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ |
| 61 | 62 | ||
| 62 | struct acpi_pci_slot { | 63 | struct acpi_pci_slot { |
| 63 | acpi_handle root_handle; /* handle of the root bridge */ | 64 | acpi_handle root_handle; /* handle of the root bridge */ |
| @@ -149,7 +150,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 149 | return AE_OK; | 150 | return AE_OK; |
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | snprintf(name, sizeof(name), "%u", (u32)sun); | 153 | snprintf(name, sizeof(name), "%llu", sun); |
| 153 | pci_slot = pci_create_slot(pci_bus, device, name, NULL); | 154 | pci_slot = pci_create_slot(pci_bus, device, name, NULL); |
| 154 | if (IS_ERR(pci_slot)) { | 155 | if (IS_ERR(pci_slot)) { |
| 155 | err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); | 156 | err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 5a09bf392ec1..22b297916519 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -43,9 +43,10 @@ | |||
| 43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
| 44 | #include <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
| 45 | #include <acpi/acpi_drivers.h> | 45 | #include <acpi/acpi_drivers.h> |
| 46 | |||
| 47 | #include "sleep.h" | 46 | #include "sleep.h" |
| 48 | 47 | ||
| 48 | #define PREFIX "ACPI: " | ||
| 49 | |||
| 49 | #define _COMPONENT ACPI_POWER_COMPONENT | 50 | #define _COMPONENT ACPI_POWER_COMPONENT |
| 50 | ACPI_MODULE_NAME("power"); | 51 | ACPI_MODULE_NAME("power"); |
| 51 | #define ACPI_POWER_CLASS "power_resource" | 52 | #define ACPI_POWER_CLASS "power_resource" |
diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c new file mode 100644 index 000000000000..e6bfd77986b8 --- /dev/null +++ b/drivers/acpi/power_meter.c | |||
| @@ -0,0 +1,1018 @@ | |||
| 1 | /* | ||
| 2 | * A hwmon driver for ACPI 4.0 power meters | ||
| 3 | * Copyright (C) 2009 IBM | ||
| 4 | * | ||
| 5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/hwmon.h> | ||
| 24 | #include <linux/hwmon-sysfs.h> | ||
| 25 | #include <linux/jiffies.h> | ||
| 26 | #include <linux/mutex.h> | ||
| 27 | #include <linux/dmi.h> | ||
| 28 | #include <linux/kdev_t.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | #include <linux/time.h> | ||
| 31 | #include <acpi/acpi_drivers.h> | ||
| 32 | #include <acpi/acpi_bus.h> | ||
| 33 | |||
| 34 | #define ACPI_POWER_METER_NAME "power_meter" | ||
| 35 | ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); | ||
| 36 | #define ACPI_POWER_METER_DEVICE_NAME "Power Meter" | ||
| 37 | #define ACPI_POWER_METER_CLASS "power_meter_resource" | ||
| 38 | |||
| 39 | #define NUM_SENSORS 17 | ||
| 40 | |||
| 41 | #define POWER_METER_CAN_MEASURE (1 << 0) | ||
| 42 | #define POWER_METER_CAN_TRIP (1 << 1) | ||
| 43 | #define POWER_METER_CAN_CAP (1 << 2) | ||
| 44 | #define POWER_METER_CAN_NOTIFY (1 << 3) | ||
| 45 | #define POWER_METER_IS_BATTERY (1 << 8) | ||
| 46 | #define UNKNOWN_HYSTERESIS 0xFFFFFFFF | ||
| 47 | |||
| 48 | #define METER_NOTIFY_CONFIG 0x80 | ||
| 49 | #define METER_NOTIFY_TRIP 0x81 | ||
| 50 | #define METER_NOTIFY_CAP 0x82 | ||
| 51 | #define METER_NOTIFY_CAPPING 0x83 | ||
| 52 | #define METER_NOTIFY_INTERVAL 0x84 | ||
| 53 | |||
| 54 | #define POWER_AVERAGE_NAME "power1_average" | ||
| 55 | #define POWER_CAP_NAME "power1_cap" | ||
| 56 | #define POWER_AVG_INTERVAL_NAME "power1_average_interval" | ||
| 57 | #define POWER_ALARM_NAME "power1_alarm" | ||
| 58 | |||
| 59 | static int cap_in_hardware; | ||
| 60 | static int force_cap_on; | ||
| 61 | |||
| 62 | static int can_cap_in_hardware(void) | ||
| 63 | { | ||
| 64 | return force_cap_on || cap_in_hardware; | ||
| 65 | } | ||
| 66 | |||
| 67 | static struct acpi_device_id power_meter_ids[] = { | ||
| 68 | {"ACPI000D", 0}, | ||
| 69 | {"", 0}, | ||
| 70 | }; | ||
| 71 | MODULE_DEVICE_TABLE(acpi, power_meter_ids); | ||
| 72 | |||
| 73 | struct acpi_power_meter_capabilities { | ||
| 74 | acpi_integer flags; | ||
| 75 | acpi_integer units; | ||
| 76 | acpi_integer type; | ||
| 77 | acpi_integer accuracy; | ||
| 78 | acpi_integer sampling_time; | ||
| 79 | acpi_integer min_avg_interval; | ||
| 80 | acpi_integer max_avg_interval; | ||
| 81 | acpi_integer hysteresis; | ||
| 82 | acpi_integer configurable_cap; | ||
| 83 | acpi_integer min_cap; | ||
| 84 | acpi_integer max_cap; | ||
| 85 | }; | ||
| 86 | |||
| 87 | struct acpi_power_meter_resource { | ||
| 88 | struct acpi_device *acpi_dev; | ||
| 89 | acpi_bus_id name; | ||
| 90 | struct mutex lock; | ||
| 91 | struct device *hwmon_dev; | ||
| 92 | struct acpi_power_meter_capabilities caps; | ||
| 93 | acpi_string model_number; | ||
| 94 | acpi_string serial_number; | ||
| 95 | acpi_string oem_info; | ||
| 96 | acpi_integer power; | ||
| 97 | acpi_integer cap; | ||
| 98 | acpi_integer avg_interval; | ||
| 99 | int sensors_valid; | ||
| 100 | unsigned long sensors_last_updated; | ||
| 101 | struct sensor_device_attribute sensors[NUM_SENSORS]; | ||
| 102 | int num_sensors; | ||
| 103 | int trip[2]; | ||
| 104 | int num_domain_devices; | ||
| 105 | struct acpi_device **domain_devices; | ||
| 106 | struct kobject *holders_dir; | ||
| 107 | }; | ||
| 108 | |||
| 109 | struct ro_sensor_template { | ||
| 110 | char *label; | ||
| 111 | ssize_t (*show)(struct device *dev, | ||
| 112 | struct device_attribute *devattr, | ||
| 113 | char *buf); | ||
| 114 | int index; | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct rw_sensor_template { | ||
| 118 | char *label; | ||
| 119 | ssize_t (*show)(struct device *dev, | ||
| 120 | struct device_attribute *devattr, | ||
| 121 | char *buf); | ||
| 122 | ssize_t (*set)(struct device *dev, | ||
| 123 | struct device_attribute *devattr, | ||
| 124 | const char *buf, size_t count); | ||
| 125 | int index; | ||
| 126 | }; | ||
| 127 | |||
| 128 | /* Averaging interval */ | ||
| 129 | static int update_avg_interval(struct acpi_power_meter_resource *resource) | ||
| 130 | { | ||
| 131 | unsigned long long data; | ||
| 132 | acpi_status status; | ||
| 133 | |||
| 134 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GAI", | ||
| 135 | NULL, &data); | ||
| 136 | if (ACPI_FAILURE(status)) { | ||
| 137 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GAI")); | ||
| 138 | return -ENODEV; | ||
| 139 | } | ||
| 140 | |||
| 141 | resource->avg_interval = data; | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static ssize_t show_avg_interval(struct device *dev, | ||
| 146 | struct device_attribute *devattr, | ||
| 147 | char *buf) | ||
| 148 | { | ||
| 149 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 150 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 151 | |||
| 152 | mutex_lock(&resource->lock); | ||
| 153 | update_avg_interval(resource); | ||
| 154 | mutex_unlock(&resource->lock); | ||
| 155 | |||
| 156 | return sprintf(buf, "%llu\n", resource->avg_interval); | ||
| 157 | } | ||
| 158 | |||
| 159 | static ssize_t set_avg_interval(struct device *dev, | ||
| 160 | struct device_attribute *devattr, | ||
| 161 | const char *buf, size_t count) | ||
| 162 | { | ||
| 163 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 164 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 165 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
| 166 | struct acpi_object_list args = { 1, &arg0 }; | ||
| 167 | int res; | ||
| 168 | unsigned long temp; | ||
| 169 | unsigned long long data; | ||
| 170 | acpi_status status; | ||
| 171 | |||
| 172 | res = strict_strtoul(buf, 10, &temp); | ||
| 173 | if (res) | ||
| 174 | return res; | ||
| 175 | |||
| 176 | if (temp > resource->caps.max_avg_interval || | ||
| 177 | temp < resource->caps.min_avg_interval) | ||
| 178 | return -EINVAL; | ||
| 179 | arg0.integer.value = temp; | ||
| 180 | |||
| 181 | mutex_lock(&resource->lock); | ||
| 182 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PAI", | ||
| 183 | &args, &data); | ||
| 184 | if (!ACPI_FAILURE(status)) | ||
| 185 | resource->avg_interval = temp; | ||
| 186 | mutex_unlock(&resource->lock); | ||
| 187 | |||
| 188 | if (ACPI_FAILURE(status)) { | ||
| 189 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PAI")); | ||
| 190 | return -EINVAL; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* _PAI returns 0 on success, nonzero otherwise */ | ||
| 194 | if (data) | ||
| 195 | return -EINVAL; | ||
| 196 | |||
| 197 | return count; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* Cap functions */ | ||
| 201 | static int update_cap(struct acpi_power_meter_resource *resource) | ||
| 202 | { | ||
| 203 | unsigned long long data; | ||
| 204 | acpi_status status; | ||
| 205 | |||
| 206 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GHL", | ||
| 207 | NULL, &data); | ||
| 208 | if (ACPI_FAILURE(status)) { | ||
| 209 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GHL")); | ||
| 210 | return -ENODEV; | ||
| 211 | } | ||
| 212 | |||
| 213 | resource->cap = data; | ||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static ssize_t show_cap(struct device *dev, | ||
| 218 | struct device_attribute *devattr, | ||
| 219 | char *buf) | ||
| 220 | { | ||
| 221 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 222 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 223 | |||
| 224 | mutex_lock(&resource->lock); | ||
| 225 | update_cap(resource); | ||
| 226 | mutex_unlock(&resource->lock); | ||
| 227 | |||
| 228 | return sprintf(buf, "%llu\n", resource->cap * 1000); | ||
| 229 | } | ||
| 230 | |||
| 231 | static ssize_t set_cap(struct device *dev, struct device_attribute *devattr, | ||
| 232 | const char *buf, size_t count) | ||
| 233 | { | ||
| 234 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 235 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 236 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | ||
| 237 | struct acpi_object_list args = { 1, &arg0 }; | ||
| 238 | int res; | ||
| 239 | unsigned long temp; | ||
| 240 | unsigned long long data; | ||
| 241 | acpi_status status; | ||
| 242 | |||
| 243 | res = strict_strtoul(buf, 10, &temp); | ||
| 244 | if (res) | ||
| 245 | return res; | ||
| 246 | |||
| 247 | temp /= 1000; | ||
| 248 | if (temp > resource->caps.max_cap || temp < resource->caps.min_cap) | ||
| 249 | return -EINVAL; | ||
| 250 | arg0.integer.value = temp; | ||
| 251 | |||
| 252 | mutex_lock(&resource->lock); | ||
| 253 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_SHL", | ||
| 254 | &args, &data); | ||
| 255 | if (!ACPI_FAILURE(status)) | ||
| 256 | resource->cap = temp; | ||
| 257 | mutex_unlock(&resource->lock); | ||
| 258 | |||
| 259 | if (ACPI_FAILURE(status)) { | ||
| 260 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SHL")); | ||
| 261 | return -EINVAL; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* _SHL returns 0 on success, nonzero otherwise */ | ||
| 265 | if (data) | ||
| 266 | return -EINVAL; | ||
| 267 | |||
| 268 | return count; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* Power meter trip points */ | ||
| 272 | static int set_acpi_trip(struct acpi_power_meter_resource *resource) | ||
| 273 | { | ||
| 274 | union acpi_object arg_objs[] = { | ||
| 275 | {ACPI_TYPE_INTEGER}, | ||
| 276 | {ACPI_TYPE_INTEGER} | ||
| 277 | }; | ||
| 278 | struct acpi_object_list args = { 2, arg_objs }; | ||
| 279 | unsigned long long data; | ||
| 280 | acpi_status status; | ||
| 281 | |||
| 282 | /* Both trip levels must be set */ | ||
| 283 | if (resource->trip[0] < 0 || resource->trip[1] < 0) | ||
| 284 | return 0; | ||
| 285 | |||
| 286 | /* This driver stores min, max; ACPI wants max, min. */ | ||
| 287 | arg_objs[0].integer.value = resource->trip[1]; | ||
| 288 | arg_objs[1].integer.value = resource->trip[0]; | ||
| 289 | |||
| 290 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PTP", | ||
| 291 | &args, &data); | ||
| 292 | if (ACPI_FAILURE(status)) { | ||
| 293 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTP")); | ||
| 294 | return -EINVAL; | ||
| 295 | } | ||
| 296 | |||
| 297 | return data; | ||
| 298 | } | ||
| 299 | |||
| 300 | static ssize_t set_trip(struct device *dev, struct device_attribute *devattr, | ||
| 301 | const char *buf, size_t count) | ||
| 302 | { | ||
| 303 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 304 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 305 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 306 | int res; | ||
| 307 | unsigned long temp; | ||
| 308 | |||
| 309 | res = strict_strtoul(buf, 10, &temp); | ||
| 310 | if (res) | ||
| 311 | return res; | ||
| 312 | |||
| 313 | temp /= 1000; | ||
| 314 | if (temp < 0) | ||
| 315 | return -EINVAL; | ||
| 316 | |||
| 317 | mutex_lock(&resource->lock); | ||
| 318 | resource->trip[attr->index - 7] = temp; | ||
| 319 | res = set_acpi_trip(resource); | ||
| 320 | mutex_unlock(&resource->lock); | ||
| 321 | |||
| 322 | if (res) | ||
| 323 | return res; | ||
| 324 | |||
| 325 | return count; | ||
| 326 | } | ||
| 327 | |||
| 328 | /* Power meter */ | ||
| 329 | static int update_meter(struct acpi_power_meter_resource *resource) | ||
| 330 | { | ||
| 331 | unsigned long long data; | ||
| 332 | acpi_status status; | ||
| 333 | unsigned long local_jiffies = jiffies; | ||
| 334 | |||
| 335 | if (time_before(local_jiffies, resource->sensors_last_updated + | ||
| 336 | msecs_to_jiffies(resource->caps.sampling_time)) && | ||
| 337 | resource->sensors_valid) | ||
| 338 | return 0; | ||
| 339 | |||
| 340 | status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PMM", | ||
| 341 | NULL, &data); | ||
| 342 | if (ACPI_FAILURE(status)) { | ||
| 343 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMM")); | ||
| 344 | return -ENODEV; | ||
| 345 | } | ||
| 346 | |||
| 347 | resource->power = data; | ||
| 348 | resource->sensors_valid = 1; | ||
| 349 | resource->sensors_last_updated = jiffies; | ||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static ssize_t show_power(struct device *dev, | ||
| 354 | struct device_attribute *devattr, | ||
| 355 | char *buf) | ||
| 356 | { | ||
| 357 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 358 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 359 | |||
| 360 | mutex_lock(&resource->lock); | ||
| 361 | update_meter(resource); | ||
| 362 | mutex_unlock(&resource->lock); | ||
| 363 | |||
| 364 | return sprintf(buf, "%llu\n", resource->power * 1000); | ||
| 365 | } | ||
| 366 | |||
| 367 | /* Miscellaneous */ | ||
| 368 | static ssize_t show_str(struct device *dev, | ||
| 369 | struct device_attribute *devattr, | ||
| 370 | char *buf) | ||
| 371 | { | ||
| 372 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 373 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 374 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 375 | acpi_string val; | ||
| 376 | |||
| 377 | switch (attr->index) { | ||
| 378 | case 0: | ||
| 379 | val = resource->model_number; | ||
| 380 | break; | ||
| 381 | case 1: | ||
| 382 | val = resource->serial_number; | ||
| 383 | break; | ||
| 384 | case 2: | ||
| 385 | val = resource->oem_info; | ||
| 386 | break; | ||
| 387 | default: | ||
| 388 | BUG(); | ||
| 389 | } | ||
| 390 | |||
| 391 | return sprintf(buf, "%s\n", val); | ||
| 392 | } | ||
| 393 | |||
| 394 | static ssize_t show_val(struct device *dev, | ||
| 395 | struct device_attribute *devattr, | ||
| 396 | char *buf) | ||
| 397 | { | ||
| 398 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 399 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 400 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 401 | acpi_integer val = 0; | ||
| 402 | |||
| 403 | switch (attr->index) { | ||
| 404 | case 0: | ||
| 405 | val = resource->caps.min_avg_interval; | ||
| 406 | break; | ||
| 407 | case 1: | ||
| 408 | val = resource->caps.max_avg_interval; | ||
| 409 | break; | ||
| 410 | case 2: | ||
| 411 | val = resource->caps.min_cap * 1000; | ||
| 412 | break; | ||
| 413 | case 3: | ||
| 414 | val = resource->caps.max_cap * 1000; | ||
| 415 | break; | ||
| 416 | case 4: | ||
| 417 | if (resource->caps.hysteresis == UNKNOWN_HYSTERESIS) | ||
| 418 | return sprintf(buf, "unknown\n"); | ||
| 419 | |||
| 420 | val = resource->caps.hysteresis * 1000; | ||
| 421 | break; | ||
| 422 | case 5: | ||
| 423 | if (resource->caps.flags & POWER_METER_IS_BATTERY) | ||
| 424 | val = 1; | ||
| 425 | else | ||
| 426 | val = 0; | ||
| 427 | break; | ||
| 428 | case 6: | ||
| 429 | if (resource->power > resource->cap) | ||
| 430 | val = 1; | ||
| 431 | else | ||
| 432 | val = 0; | ||
| 433 | break; | ||
| 434 | case 7: | ||
| 435 | case 8: | ||
| 436 | if (resource->trip[attr->index - 7] < 0) | ||
| 437 | return sprintf(buf, "unknown\n"); | ||
| 438 | |||
| 439 | val = resource->trip[attr->index - 7] * 1000; | ||
| 440 | break; | ||
| 441 | default: | ||
| 442 | BUG(); | ||
| 443 | } | ||
| 444 | |||
| 445 | return sprintf(buf, "%llu\n", val); | ||
| 446 | } | ||
| 447 | |||
| 448 | static ssize_t show_accuracy(struct device *dev, | ||
| 449 | struct device_attribute *devattr, | ||
| 450 | char *buf) | ||
| 451 | { | ||
| 452 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 453 | struct acpi_power_meter_resource *resource = acpi_dev->driver_data; | ||
| 454 | unsigned int acc = resource->caps.accuracy; | ||
| 455 | |||
| 456 | return sprintf(buf, "%u.%u%%\n", acc / 1000, acc % 1000); | ||
| 457 | } | ||
| 458 | |||
| 459 | static ssize_t show_name(struct device *dev, | ||
| 460 | struct device_attribute *devattr, | ||
| 461 | char *buf) | ||
| 462 | { | ||
| 463 | return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME); | ||
| 464 | } | ||
| 465 | |||
| 466 | /* Sensor descriptions. If you add a sensor, update NUM_SENSORS above! */ | ||
| 467 | static struct ro_sensor_template meter_ro_attrs[] = { | ||
| 468 | {POWER_AVERAGE_NAME, show_power, 0}, | ||
| 469 | {"power1_accuracy", show_accuracy, 0}, | ||
| 470 | {"power1_average_interval_min", show_val, 0}, | ||
| 471 | {"power1_average_interval_max", show_val, 1}, | ||
| 472 | {"power1_is_battery", show_val, 5}, | ||
| 473 | {NULL, NULL, 0}, | ||
| 474 | }; | ||
| 475 | |||
| 476 | static struct rw_sensor_template meter_rw_attrs[] = { | ||
| 477 | {POWER_AVG_INTERVAL_NAME, show_avg_interval, set_avg_interval, 0}, | ||
| 478 | {NULL, NULL, NULL, 0}, | ||
| 479 | }; | ||
| 480 | |||
| 481 | static struct ro_sensor_template misc_cap_attrs[] = { | ||
| 482 | {"power1_cap_min", show_val, 2}, | ||
| 483 | {"power1_cap_max", show_val, 3}, | ||
| 484 | {"power1_cap_hyst", show_val, 4}, | ||
| 485 | {POWER_ALARM_NAME, show_val, 6}, | ||
| 486 | {NULL, NULL, 0}, | ||
| 487 | }; | ||
| 488 | |||
| 489 | static struct ro_sensor_template ro_cap_attrs[] = { | ||
| 490 | {POWER_CAP_NAME, show_cap, 0}, | ||
| 491 | {NULL, NULL, 0}, | ||
| 492 | }; | ||
| 493 | |||
| 494 | static struct rw_sensor_template rw_cap_attrs[] = { | ||
| 495 | {POWER_CAP_NAME, show_cap, set_cap, 0}, | ||
| 496 | {NULL, NULL, NULL, 0}, | ||
| 497 | }; | ||
| 498 | |||
| 499 | static struct rw_sensor_template trip_attrs[] = { | ||
| 500 | {"power1_average_min", show_val, set_trip, 7}, | ||
| 501 | {"power1_average_max", show_val, set_trip, 8}, | ||
| 502 | {NULL, NULL, NULL, 0}, | ||
| 503 | }; | ||
| 504 | |||
| 505 | static struct ro_sensor_template misc_attrs[] = { | ||
| 506 | {"name", show_name, 0}, | ||
| 507 | {"power1_model_number", show_str, 0}, | ||
| 508 | {"power1_oem_info", show_str, 2}, | ||
| 509 | {"power1_serial_number", show_str, 1}, | ||
| 510 | {NULL, NULL, 0}, | ||
| 511 | }; | ||
| 512 | |||
| 513 | /* Read power domain data */ | ||
| 514 | static void remove_domain_devices(struct acpi_power_meter_resource *resource) | ||
| 515 | { | ||
| 516 | int i; | ||
| 517 | |||
| 518 | if (!resource->num_domain_devices) | ||
| 519 | return; | ||
| 520 | |||
| 521 | for (i = 0; i < resource->num_domain_devices; i++) { | ||
| 522 | struct acpi_device *obj = resource->domain_devices[i]; | ||
| 523 | if (!obj) | ||
| 524 | continue; | ||
| 525 | |||
| 526 | sysfs_remove_link(resource->holders_dir, | ||
| 527 | kobject_name(&obj->dev.kobj)); | ||
| 528 | put_device(&obj->dev); | ||
| 529 | } | ||
| 530 | |||
| 531 | kfree(resource->domain_devices); | ||
| 532 | kobject_put(resource->holders_dir); | ||
| 533 | } | ||
| 534 | |||
| 535 | static int read_domain_devices(struct acpi_power_meter_resource *resource) | ||
| 536 | { | ||
| 537 | int res = 0; | ||
| 538 | int i; | ||
| 539 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 540 | union acpi_object *pss; | ||
| 541 | acpi_status status; | ||
| 542 | |||
| 543 | status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMD", NULL, | ||
| 544 | &buffer); | ||
| 545 | if (ACPI_FAILURE(status)) { | ||
| 546 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMD")); | ||
| 547 | return -ENODEV; | ||
| 548 | } | ||
| 549 | |||
| 550 | pss = buffer.pointer; | ||
| 551 | if (!pss || | ||
| 552 | pss->type != ACPI_TYPE_PACKAGE) { | ||
| 553 | dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME | ||
| 554 | "Invalid _PMD data\n"); | ||
| 555 | res = -EFAULT; | ||
| 556 | goto end; | ||
| 557 | } | ||
| 558 | |||
| 559 | if (!pss->package.count) | ||
| 560 | goto end; | ||
| 561 | |||
| 562 | resource->domain_devices = kzalloc(sizeof(struct acpi_device *) * | ||
| 563 | pss->package.count, GFP_KERNEL); | ||
| 564 | if (!resource->domain_devices) { | ||
| 565 | res = -ENOMEM; | ||
| 566 | goto end; | ||
| 567 | } | ||
| 568 | |||
| 569 | resource->holders_dir = kobject_create_and_add("measures", | ||
| 570 | &resource->acpi_dev->dev.kobj); | ||
| 571 | if (!resource->holders_dir) { | ||
| 572 | res = -ENOMEM; | ||
| 573 | goto exit_free; | ||
| 574 | } | ||
| 575 | |||
| 576 | resource->num_domain_devices = pss->package.count; | ||
| 577 | |||
| 578 | for (i = 0; i < pss->package.count; i++) { | ||
| 579 | struct acpi_device *obj; | ||
| 580 | union acpi_object *element = &(pss->package.elements[i]); | ||
| 581 | |||
| 582 | /* Refuse non-references */ | ||
| 583 | if (element->type != ACPI_TYPE_LOCAL_REFERENCE) | ||
| 584 | continue; | ||
| 585 | |||
| 586 | /* Create a symlink to domain objects */ | ||
| 587 | resource->domain_devices[i] = NULL; | ||
| 588 | status = acpi_bus_get_device(element->reference.handle, | ||
| 589 | &resource->domain_devices[i]); | ||
| 590 | if (ACPI_FAILURE(status)) | ||
| 591 | continue; | ||
| 592 | |||
| 593 | obj = resource->domain_devices[i]; | ||
| 594 | get_device(&obj->dev); | ||
| 595 | |||
| 596 | res = sysfs_create_link(resource->holders_dir, &obj->dev.kobj, | ||
| 597 | kobject_name(&obj->dev.kobj)); | ||
| 598 | if (res) { | ||
| 599 | put_device(&obj->dev); | ||
| 600 | resource->domain_devices[i] = NULL; | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 604 | res = 0; | ||
| 605 | goto end; | ||
| 606 | |||
| 607 | exit_free: | ||
| 608 | kfree(resource->domain_devices); | ||
| 609 | end: | ||
| 610 | kfree(buffer.pointer); | ||
| 611 | return res; | ||
| 612 | } | ||
| 613 | |||
| 614 | /* Registration and deregistration */ | ||
| 615 | static int register_ro_attrs(struct acpi_power_meter_resource *resource, | ||
| 616 | struct ro_sensor_template *ro) | ||
| 617 | { | ||
| 618 | struct device *dev = &resource->acpi_dev->dev; | ||
| 619 | struct sensor_device_attribute *sensors = | ||
| 620 | &resource->sensors[resource->num_sensors]; | ||
| 621 | int res = 0; | ||
| 622 | |||
| 623 | while (ro->label) { | ||
| 624 | sensors->dev_attr.attr.name = ro->label; | ||
| 625 | sensors->dev_attr.attr.mode = S_IRUGO; | ||
| 626 | sensors->dev_attr.show = ro->show; | ||
| 627 | sensors->index = ro->index; | ||
| 628 | |||
| 629 | res = device_create_file(dev, &sensors->dev_attr); | ||
| 630 | if (res) { | ||
| 631 | sensors->dev_attr.attr.name = NULL; | ||
| 632 | goto error; | ||
| 633 | } | ||
| 634 | sensors++; | ||
| 635 | resource->num_sensors++; | ||
| 636 | ro++; | ||
| 637 | } | ||
| 638 | |||
| 639 | error: | ||
| 640 | return res; | ||
| 641 | } | ||
| 642 | |||
| 643 | static int register_rw_attrs(struct acpi_power_meter_resource *resource, | ||
| 644 | struct rw_sensor_template *rw) | ||
| 645 | { | ||
| 646 | struct device *dev = &resource->acpi_dev->dev; | ||
| 647 | struct sensor_device_attribute *sensors = | ||
| 648 | &resource->sensors[resource->num_sensors]; | ||
| 649 | int res = 0; | ||
| 650 | |||
| 651 | while (rw->label) { | ||
| 652 | sensors->dev_attr.attr.name = rw->label; | ||
| 653 | sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; | ||
| 654 | sensors->dev_attr.show = rw->show; | ||
| 655 | sensors->dev_attr.store = rw->set; | ||
| 656 | sensors->index = rw->index; | ||
| 657 | |||
| 658 | res = device_create_file(dev, &sensors->dev_attr); | ||
| 659 | if (res) { | ||
| 660 | sensors->dev_attr.attr.name = NULL; | ||
| 661 | goto error; | ||
| 662 | } | ||
| 663 | sensors++; | ||
| 664 | resource->num_sensors++; | ||
| 665 | rw++; | ||
| 666 | } | ||
| 667 | |||
| 668 | error: | ||
| 669 | return res; | ||
| 670 | } | ||
| 671 | |||
| 672 | static void remove_attrs(struct acpi_power_meter_resource *resource) | ||
| 673 | { | ||
| 674 | int i; | ||
| 675 | |||
| 676 | for (i = 0; i < resource->num_sensors; i++) { | ||
| 677 | if (!resource->sensors[i].dev_attr.attr.name) | ||
| 678 | continue; | ||
| 679 | device_remove_file(&resource->acpi_dev->dev, | ||
| 680 | &resource->sensors[i].dev_attr); | ||
| 681 | } | ||
| 682 | |||
| 683 | remove_domain_devices(resource); | ||
| 684 | |||
| 685 | resource->num_sensors = 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | static int setup_attrs(struct acpi_power_meter_resource *resource) | ||
| 689 | { | ||
| 690 | int res = 0; | ||
| 691 | |||
| 692 | res = read_domain_devices(resource); | ||
| 693 | if (res) | ||
| 694 | return res; | ||
| 695 | |||
| 696 | if (resource->caps.flags & POWER_METER_CAN_MEASURE) { | ||
| 697 | res = register_ro_attrs(resource, meter_ro_attrs); | ||
| 698 | if (res) | ||
| 699 | goto error; | ||
| 700 | res = register_rw_attrs(resource, meter_rw_attrs); | ||
| 701 | if (res) | ||
| 702 | goto error; | ||
| 703 | } | ||
| 704 | |||
| 705 | if (resource->caps.flags & POWER_METER_CAN_CAP) { | ||
| 706 | if (!can_cap_in_hardware()) { | ||
| 707 | dev_err(&resource->acpi_dev->dev, | ||
| 708 | "Ignoring unsafe software power cap!\n"); | ||
| 709 | goto skip_unsafe_cap; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (resource->caps.configurable_cap) { | ||
| 713 | res = register_rw_attrs(resource, rw_cap_attrs); | ||
| 714 | if (res) | ||
| 715 | goto error; | ||
| 716 | } else { | ||
| 717 | res = register_ro_attrs(resource, ro_cap_attrs); | ||
| 718 | if (res) | ||
| 719 | goto error; | ||
| 720 | } | ||
| 721 | res = register_ro_attrs(resource, misc_cap_attrs); | ||
| 722 | if (res) | ||
| 723 | goto error; | ||
| 724 | } | ||
| 725 | skip_unsafe_cap: | ||
| 726 | |||
| 727 | if (resource->caps.flags & POWER_METER_CAN_TRIP) { | ||
| 728 | res = register_rw_attrs(resource, trip_attrs); | ||
| 729 | if (res) | ||
| 730 | goto error; | ||
| 731 | } | ||
| 732 | |||
| 733 | res = register_ro_attrs(resource, misc_attrs); | ||
| 734 | if (res) | ||
| 735 | goto error; | ||
| 736 | |||
| 737 | return res; | ||
| 738 | error: | ||
| 739 | remove_domain_devices(resource); | ||
| 740 | remove_attrs(resource); | ||
| 741 | return res; | ||
| 742 | } | ||
| 743 | |||
| 744 | static void free_capabilities(struct acpi_power_meter_resource *resource) | ||
| 745 | { | ||
| 746 | acpi_string *str; | ||
| 747 | int i; | ||
| 748 | |||
| 749 | str = &resource->model_number; | ||
| 750 | for (i = 0; i < 3; i++, str++) | ||
| 751 | kfree(*str); | ||
| 752 | } | ||
| 753 | |||
| 754 | static int read_capabilities(struct acpi_power_meter_resource *resource) | ||
| 755 | { | ||
| 756 | int res = 0; | ||
| 757 | int i; | ||
| 758 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 759 | struct acpi_buffer state = { 0, NULL }; | ||
| 760 | struct acpi_buffer format = { sizeof("NNNNNNNNNNN"), "NNNNNNNNNNN" }; | ||
| 761 | union acpi_object *pss; | ||
| 762 | acpi_string *str; | ||
| 763 | acpi_status status; | ||
| 764 | |||
| 765 | status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMC", NULL, | ||
| 766 | &buffer); | ||
| 767 | if (ACPI_FAILURE(status)) { | ||
| 768 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMC")); | ||
| 769 | return -ENODEV; | ||
| 770 | } | ||
| 771 | |||
| 772 | pss = buffer.pointer; | ||
| 773 | if (!pss || | ||
| 774 | pss->type != ACPI_TYPE_PACKAGE || | ||
| 775 | pss->package.count != 14) { | ||
| 776 | dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME | ||
| 777 | "Invalid _PMC data\n"); | ||
| 778 | res = -EFAULT; | ||
| 779 | goto end; | ||
| 780 | } | ||
| 781 | |||
| 782 | /* Grab all the integer data at once */ | ||
| 783 | state.length = sizeof(struct acpi_power_meter_capabilities); | ||
| 784 | state.pointer = &resource->caps; | ||
| 785 | |||
| 786 | status = acpi_extract_package(pss, &format, &state); | ||
| 787 | if (ACPI_FAILURE(status)) { | ||
| 788 | ACPI_EXCEPTION((AE_INFO, status, "Invalid data")); | ||
| 789 | res = -EFAULT; | ||
| 790 | goto end; | ||
| 791 | } | ||
| 792 | |||
| 793 | if (resource->caps.units) { | ||
| 794 | dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME | ||
| 795 | "Unknown units %llu.\n", | ||
| 796 | resource->caps.units); | ||
| 797 | res = -EINVAL; | ||
| 798 | goto end; | ||
| 799 | } | ||
| 800 | |||
| 801 | /* Grab the string data */ | ||
| 802 | str = &resource->model_number; | ||
| 803 | |||
| 804 | for (i = 11; i < 14; i++) { | ||
| 805 | union acpi_object *element = &(pss->package.elements[i]); | ||
| 806 | |||
| 807 | if (element->type != ACPI_TYPE_STRING) { | ||
| 808 | res = -EINVAL; | ||
| 809 | goto error; | ||
| 810 | } | ||
| 811 | |||
| 812 | *str = kzalloc(sizeof(u8) * (element->string.length + 1), | ||
| 813 | GFP_KERNEL); | ||
| 814 | if (!*str) { | ||
| 815 | res = -ENOMEM; | ||
| 816 | goto error; | ||
| 817 | } | ||
| 818 | |||
| 819 | strncpy(*str, element->string.pointer, element->string.length); | ||
| 820 | str++; | ||
| 821 | } | ||
| 822 | |||
| 823 | dev_info(&resource->acpi_dev->dev, "Found ACPI power meter.\n"); | ||
| 824 | goto end; | ||
| 825 | error: | ||
| 826 | str = &resource->model_number; | ||
| 827 | for (i = 0; i < 3; i++, str++) | ||
| 828 | kfree(*str); | ||
| 829 | end: | ||
| 830 | kfree(buffer.pointer); | ||
| 831 | return res; | ||
| 832 | } | ||
| 833 | |||
| 834 | /* Handle ACPI event notifications */ | ||
| 835 | static void acpi_power_meter_notify(struct acpi_device *device, u32 event) | ||
| 836 | { | ||
| 837 | struct acpi_power_meter_resource *resource; | ||
| 838 | int res; | ||
| 839 | |||
| 840 | if (!device || !acpi_driver_data(device)) | ||
| 841 | return; | ||
| 842 | |||
| 843 | resource = acpi_driver_data(device); | ||
| 844 | |||
| 845 | mutex_lock(&resource->lock); | ||
| 846 | switch (event) { | ||
| 847 | case METER_NOTIFY_CONFIG: | ||
| 848 | free_capabilities(resource); | ||
| 849 | res = read_capabilities(resource); | ||
| 850 | if (res) | ||
| 851 | break; | ||
| 852 | |||
| 853 | remove_attrs(resource); | ||
| 854 | setup_attrs(resource); | ||
| 855 | break; | ||
| 856 | case METER_NOTIFY_TRIP: | ||
| 857 | sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME); | ||
| 858 | update_meter(resource); | ||
| 859 | break; | ||
| 860 | case METER_NOTIFY_CAP: | ||
| 861 | sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME); | ||
| 862 | update_cap(resource); | ||
| 863 | break; | ||
| 864 | case METER_NOTIFY_INTERVAL: | ||
| 865 | sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME); | ||
| 866 | update_avg_interval(resource); | ||
| 867 | break; | ||
| 868 | case METER_NOTIFY_CAPPING: | ||
| 869 | sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME); | ||
| 870 | dev_info(&device->dev, "Capping in progress.\n"); | ||
| 871 | break; | ||
| 872 | default: | ||
| 873 | BUG(); | ||
| 874 | } | ||
| 875 | mutex_unlock(&resource->lock); | ||
| 876 | |||
| 877 | acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS, | ||
| 878 | dev_name(&device->dev), event, 0); | ||
| 879 | } | ||
| 880 | |||
| 881 | static int acpi_power_meter_add(struct acpi_device *device) | ||
| 882 | { | ||
| 883 | int res; | ||
| 884 | struct acpi_power_meter_resource *resource; | ||
| 885 | |||
| 886 | if (!device) | ||
| 887 | return -EINVAL; | ||
| 888 | |||
| 889 | resource = kzalloc(sizeof(struct acpi_power_meter_resource), | ||
| 890 | GFP_KERNEL); | ||
| 891 | if (!resource) | ||
| 892 | return -ENOMEM; | ||
| 893 | |||
| 894 | resource->sensors_valid = 0; | ||
| 895 | resource->acpi_dev = device; | ||
| 896 | mutex_init(&resource->lock); | ||
| 897 | strcpy(acpi_device_name(device), ACPI_POWER_METER_DEVICE_NAME); | ||
| 898 | strcpy(acpi_device_class(device), ACPI_POWER_METER_CLASS); | ||
| 899 | device->driver_data = resource; | ||
| 900 | |||
| 901 | free_capabilities(resource); | ||
| 902 | res = read_capabilities(resource); | ||
| 903 | if (res) | ||
| 904 | goto exit_free; | ||
| 905 | |||
| 906 | resource->trip[0] = resource->trip[1] = -1; | ||
| 907 | |||
| 908 | res = setup_attrs(resource); | ||
| 909 | if (res) | ||
| 910 | goto exit_free; | ||
| 911 | |||
| 912 | resource->hwmon_dev = hwmon_device_register(&device->dev); | ||
| 913 | if (IS_ERR(resource->hwmon_dev)) { | ||
| 914 | res = PTR_ERR(resource->hwmon_dev); | ||
| 915 | goto exit_remove; | ||
| 916 | } | ||
| 917 | |||
| 918 | res = 0; | ||
| 919 | goto exit; | ||
| 920 | |||
| 921 | exit_remove: | ||
| 922 | remove_attrs(resource); | ||
| 923 | exit_free: | ||
| 924 | kfree(resource); | ||
| 925 | exit: | ||
| 926 | return res; | ||
| 927 | } | ||
| 928 | |||
| 929 | static int acpi_power_meter_remove(struct acpi_device *device, int type) | ||
| 930 | { | ||
| 931 | struct acpi_power_meter_resource *resource; | ||
| 932 | |||
| 933 | if (!device || !acpi_driver_data(device)) | ||
| 934 | return -EINVAL; | ||
| 935 | |||
| 936 | resource = acpi_driver_data(device); | ||
| 937 | hwmon_device_unregister(resource->hwmon_dev); | ||
| 938 | |||
| 939 | free_capabilities(resource); | ||
| 940 | remove_attrs(resource); | ||
| 941 | |||
| 942 | kfree(resource); | ||
| 943 | return 0; | ||
| 944 | } | ||
| 945 | |||
| 946 | static int acpi_power_meter_resume(struct acpi_device *device) | ||
| 947 | { | ||
| 948 | struct acpi_power_meter_resource *resource; | ||
| 949 | |||
| 950 | if (!device || !acpi_driver_data(device)) | ||
| 951 | return -EINVAL; | ||
| 952 | |||
| 953 | resource = acpi_driver_data(device); | ||
| 954 | free_capabilities(resource); | ||
| 955 | read_capabilities(resource); | ||
| 956 | |||
| 957 | return 0; | ||
| 958 | } | ||
| 959 | |||
| 960 | static struct acpi_driver acpi_power_meter_driver = { | ||
| 961 | .name = "power_meter", | ||
| 962 | .class = ACPI_POWER_METER_CLASS, | ||
| 963 | .ids = power_meter_ids, | ||
| 964 | .ops = { | ||
| 965 | .add = acpi_power_meter_add, | ||
| 966 | .remove = acpi_power_meter_remove, | ||
| 967 | .resume = acpi_power_meter_resume, | ||
| 968 | .notify = acpi_power_meter_notify, | ||
| 969 | }, | ||
| 970 | }; | ||
| 971 | |||
| 972 | /* Module init/exit routines */ | ||
| 973 | static int __init enable_cap_knobs(const struct dmi_system_id *d) | ||
| 974 | { | ||
| 975 | cap_in_hardware = 1; | ||
| 976 | return 0; | ||
| 977 | } | ||
| 978 | |||
| 979 | static struct dmi_system_id __initdata pm_dmi_table[] = { | ||
| 980 | { | ||
| 981 | enable_cap_knobs, "IBM Active Energy Manager", | ||
| 982 | { | ||
| 983 | DMI_MATCH(DMI_SYS_VENDOR, "IBM") | ||
| 984 | }, | ||
| 985 | }, | ||
| 986 | {} | ||
| 987 | }; | ||
| 988 | |||
| 989 | static int __init acpi_power_meter_init(void) | ||
| 990 | { | ||
| 991 | int result; | ||
| 992 | |||
| 993 | if (acpi_disabled) | ||
| 994 | return -ENODEV; | ||
| 995 | |||
| 996 | dmi_check_system(pm_dmi_table); | ||
| 997 | |||
| 998 | result = acpi_bus_register_driver(&acpi_power_meter_driver); | ||
| 999 | if (result < 0) | ||
| 1000 | return -ENODEV; | ||
| 1001 | |||
| 1002 | return 0; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static void __exit acpi_power_meter_exit(void) | ||
| 1006 | { | ||
| 1007 | acpi_bus_unregister_driver(&acpi_power_meter_driver); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
| 1011 | MODULE_DESCRIPTION("ACPI 4.0 power meter driver"); | ||
| 1012 | MODULE_LICENSE("GPL"); | ||
| 1013 | |||
| 1014 | module_param(force_cap_on, bool, 0644); | ||
| 1015 | MODULE_PARM_DESC(force_cap_on, "Enable power cap even it is unsafe to do so."); | ||
| 1016 | |||
| 1017 | module_init(acpi_power_meter_init); | ||
| 1018 | module_exit(acpi_power_meter_exit); | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 2cc4b3033872..c2d4d6e09364 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -59,6 +59,8 @@ | |||
| 59 | #include <acpi/acpi_drivers.h> | 59 | #include <acpi/acpi_drivers.h> |
| 60 | #include <acpi/processor.h> | 60 | #include <acpi/processor.h> |
| 61 | 61 | ||
| 62 | #define PREFIX "ACPI: " | ||
| 63 | |||
| 62 | #define ACPI_PROCESSOR_CLASS "processor" | 64 | #define ACPI_PROCESSOR_CLASS "processor" |
| 63 | #define ACPI_PROCESSOR_DEVICE_NAME "Processor" | 65 | #define ACPI_PROCESSOR_DEVICE_NAME "Processor" |
| 64 | #define ACPI_PROCESSOR_FILE_INFO "info" | 66 | #define ACPI_PROCESSOR_FILE_INFO "info" |
| @@ -79,9 +81,10 @@ MODULE_DESCRIPTION("ACPI Processor Driver"); | |||
| 79 | MODULE_LICENSE("GPL"); | 81 | MODULE_LICENSE("GPL"); |
| 80 | 82 | ||
| 81 | static int acpi_processor_add(struct acpi_device *device); | 83 | static int acpi_processor_add(struct acpi_device *device); |
| 82 | static int acpi_processor_start(struct acpi_device *device); | ||
| 83 | static int acpi_processor_remove(struct acpi_device *device, int type); | 84 | static int acpi_processor_remove(struct acpi_device *device, int type); |
| 85 | #ifdef CONFIG_ACPI_PROCFS | ||
| 84 | static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); | 86 | static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); |
| 87 | #endif | ||
| 85 | static void acpi_processor_notify(struct acpi_device *device, u32 event); | 88 | static void acpi_processor_notify(struct acpi_device *device, u32 event); |
| 86 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); | 89 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); |
| 87 | static int acpi_processor_handle_eject(struct acpi_processor *pr); | 90 | static int acpi_processor_handle_eject(struct acpi_processor *pr); |
| @@ -101,7 +104,6 @@ static struct acpi_driver acpi_processor_driver = { | |||
| 101 | .ops = { | 104 | .ops = { |
| 102 | .add = acpi_processor_add, | 105 | .add = acpi_processor_add, |
| 103 | .remove = acpi_processor_remove, | 106 | .remove = acpi_processor_remove, |
| 104 | .start = acpi_processor_start, | ||
| 105 | .suspend = acpi_processor_suspend, | 107 | .suspend = acpi_processor_suspend, |
| 106 | .resume = acpi_processor_resume, | 108 | .resume = acpi_processor_resume, |
| 107 | .notify = acpi_processor_notify, | 109 | .notify = acpi_processor_notify, |
| @@ -110,7 +112,7 @@ static struct acpi_driver acpi_processor_driver = { | |||
| 110 | 112 | ||
| 111 | #define INSTALL_NOTIFY_HANDLER 1 | 113 | #define INSTALL_NOTIFY_HANDLER 1 |
| 112 | #define UNINSTALL_NOTIFY_HANDLER 2 | 114 | #define UNINSTALL_NOTIFY_HANDLER 2 |
| 113 | 115 | #ifdef CONFIG_ACPI_PROCFS | |
| 114 | static const struct file_operations acpi_processor_info_fops = { | 116 | static const struct file_operations acpi_processor_info_fops = { |
| 115 | .owner = THIS_MODULE, | 117 | .owner = THIS_MODULE, |
| 116 | .open = acpi_processor_info_open_fs, | 118 | .open = acpi_processor_info_open_fs, |
| @@ -118,6 +120,7 @@ static const struct file_operations acpi_processor_info_fops = { | |||
| 118 | .llseek = seq_lseek, | 120 | .llseek = seq_lseek, |
| 119 | .release = single_release, | 121 | .release = single_release, |
| 120 | }; | 122 | }; |
| 123 | #endif | ||
| 121 | 124 | ||
| 122 | DEFINE_PER_CPU(struct acpi_processor *, processors); | 125 | DEFINE_PER_CPU(struct acpi_processor *, processors); |
| 123 | struct acpi_processor_errata errata __read_mostly; | 126 | struct acpi_processor_errata errata __read_mostly; |
| @@ -316,6 +319,7 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr) | |||
| 316 | FS Interface (/proc) | 319 | FS Interface (/proc) |
| 317 | -------------------------------------------------------------------------- */ | 320 | -------------------------------------------------------------------------- */ |
| 318 | 321 | ||
| 322 | #ifdef CONFIG_ACPI_PROCFS | ||
| 319 | static struct proc_dir_entry *acpi_processor_dir = NULL; | 323 | static struct proc_dir_entry *acpi_processor_dir = NULL; |
| 320 | 324 | ||
| 321 | static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) | 325 | static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) |
| @@ -388,7 +392,6 @@ static int acpi_processor_add_fs(struct acpi_device *device) | |||
| 388 | return -EIO; | 392 | return -EIO; |
| 389 | return 0; | 393 | return 0; |
| 390 | } | 394 | } |
| 391 | |||
| 392 | static int acpi_processor_remove_fs(struct acpi_device *device) | 395 | static int acpi_processor_remove_fs(struct acpi_device *device) |
| 393 | { | 396 | { |
| 394 | 397 | ||
| @@ -405,6 +408,16 @@ static int acpi_processor_remove_fs(struct acpi_device *device) | |||
| 405 | 408 | ||
| 406 | return 0; | 409 | return 0; |
| 407 | } | 410 | } |
| 411 | #else | ||
| 412 | static inline int acpi_processor_add_fs(struct acpi_device *device) | ||
| 413 | { | ||
| 414 | return 0; | ||
| 415 | } | ||
| 416 | static inline int acpi_processor_remove_fs(struct acpi_device *device) | ||
| 417 | { | ||
| 418 | return 0; | ||
| 419 | } | ||
| 420 | #endif | ||
| 408 | 421 | ||
| 409 | /* Use the acpiid in MADT to map cpus in case of SMP */ | 422 | /* Use the acpiid in MADT to map cpus in case of SMP */ |
| 410 | 423 | ||
| @@ -698,92 +711,6 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
| 698 | 711 | ||
| 699 | static DEFINE_PER_CPU(void *, processor_device_array); | 712 | static DEFINE_PER_CPU(void *, processor_device_array); |
| 700 | 713 | ||
| 701 | static int __cpuinit acpi_processor_start(struct acpi_device *device) | ||
| 702 | { | ||
| 703 | int result = 0; | ||
| 704 | struct acpi_processor *pr; | ||
| 705 | struct sys_device *sysdev; | ||
| 706 | |||
| 707 | pr = acpi_driver_data(device); | ||
| 708 | |||
| 709 | result = acpi_processor_get_info(device); | ||
| 710 | if (result) { | ||
| 711 | /* Processor is physically not present */ | ||
| 712 | return 0; | ||
| 713 | } | ||
| 714 | |||
| 715 | BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); | ||
| 716 | |||
| 717 | /* | ||
| 718 | * Buggy BIOS check | ||
| 719 | * ACPI id of processors can be reported wrongly by the BIOS. | ||
| 720 | * Don't trust it blindly | ||
| 721 | */ | ||
| 722 | if (per_cpu(processor_device_array, pr->id) != NULL && | ||
| 723 | per_cpu(processor_device_array, pr->id) != device) { | ||
| 724 | printk(KERN_WARNING "BIOS reported wrong ACPI id " | ||
| 725 | "for the processor\n"); | ||
| 726 | return -ENODEV; | ||
| 727 | } | ||
| 728 | per_cpu(processor_device_array, pr->id) = device; | ||
| 729 | |||
| 730 | per_cpu(processors, pr->id) = pr; | ||
| 731 | |||
| 732 | result = acpi_processor_add_fs(device); | ||
| 733 | if (result) | ||
| 734 | goto end; | ||
| 735 | |||
| 736 | sysdev = get_cpu_sysdev(pr->id); | ||
| 737 | if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) | ||
| 738 | return -EFAULT; | ||
| 739 | |||
| 740 | /* _PDC call should be done before doing anything else (if reqd.). */ | ||
| 741 | arch_acpi_processor_init_pdc(pr); | ||
| 742 | acpi_processor_set_pdc(pr); | ||
| 743 | arch_acpi_processor_cleanup_pdc(pr); | ||
| 744 | |||
| 745 | #ifdef CONFIG_CPU_FREQ | ||
| 746 | acpi_processor_ppc_has_changed(pr); | ||
| 747 | #endif | ||
| 748 | acpi_processor_get_throttling_info(pr); | ||
| 749 | acpi_processor_get_limit_info(pr); | ||
| 750 | |||
| 751 | |||
| 752 | acpi_processor_power_init(pr, device); | ||
| 753 | |||
| 754 | pr->cdev = thermal_cooling_device_register("Processor", device, | ||
| 755 | &processor_cooling_ops); | ||
| 756 | if (IS_ERR(pr->cdev)) { | ||
| 757 | result = PTR_ERR(pr->cdev); | ||
| 758 | goto end; | ||
| 759 | } | ||
| 760 | |||
| 761 | dev_info(&device->dev, "registered as cooling_device%d\n", | ||
| 762 | pr->cdev->id); | ||
| 763 | |||
| 764 | result = sysfs_create_link(&device->dev.kobj, | ||
| 765 | &pr->cdev->device.kobj, | ||
| 766 | "thermal_cooling"); | ||
| 767 | if (result) | ||
| 768 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 769 | result = sysfs_create_link(&pr->cdev->device.kobj, | ||
| 770 | &device->dev.kobj, | ||
| 771 | "device"); | ||
| 772 | if (result) | ||
| 773 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 774 | |||
| 775 | if (pr->flags.throttling) { | ||
| 776 | printk(KERN_INFO PREFIX "%s [%s] (supports", | ||
| 777 | acpi_device_name(device), acpi_device_bid(device)); | ||
| 778 | printk(" %d throttling states", pr->throttling.state_count); | ||
| 779 | printk(")\n"); | ||
| 780 | } | ||
| 781 | |||
| 782 | end: | ||
| 783 | |||
| 784 | return result; | ||
| 785 | } | ||
| 786 | |||
| 787 | static void acpi_processor_notify(struct acpi_device *device, u32 event) | 714 | static void acpi_processor_notify(struct acpi_device *device, u32 event) |
| 788 | { | 715 | { |
| 789 | struct acpi_processor *pr = acpi_driver_data(device); | 716 | struct acpi_processor *pr = acpi_driver_data(device); |
| @@ -846,10 +773,8 @@ static struct notifier_block acpi_cpu_notifier = | |||
| 846 | static int acpi_processor_add(struct acpi_device *device) | 773 | static int acpi_processor_add(struct acpi_device *device) |
| 847 | { | 774 | { |
| 848 | struct acpi_processor *pr = NULL; | 775 | struct acpi_processor *pr = NULL; |
| 849 | 776 | int result = 0; | |
| 850 | 777 | struct sys_device *sysdev; | |
| 851 | if (!device) | ||
| 852 | return -EINVAL; | ||
| 853 | 778 | ||
| 854 | pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); | 779 | pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); |
| 855 | if (!pr) | 780 | if (!pr) |
| @@ -865,7 +790,100 @@ static int acpi_processor_add(struct acpi_device *device) | |||
| 865 | strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); | 790 | strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); |
| 866 | device->driver_data = pr; | 791 | device->driver_data = pr; |
| 867 | 792 | ||
| 793 | result = acpi_processor_get_info(device); | ||
| 794 | if (result) { | ||
| 795 | /* Processor is physically not present */ | ||
| 796 | return 0; | ||
| 797 | } | ||
| 798 | |||
| 799 | BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); | ||
| 800 | |||
| 801 | /* | ||
| 802 | * Buggy BIOS check | ||
| 803 | * ACPI id of processors can be reported wrongly by the BIOS. | ||
| 804 | * Don't trust it blindly | ||
| 805 | */ | ||
| 806 | if (per_cpu(processor_device_array, pr->id) != NULL && | ||
| 807 | per_cpu(processor_device_array, pr->id) != device) { | ||
| 808 | printk(KERN_WARNING "BIOS reported wrong ACPI id " | ||
| 809 | "for the processor\n"); | ||
| 810 | result = -ENODEV; | ||
| 811 | goto err_free_cpumask; | ||
| 812 | } | ||
| 813 | per_cpu(processor_device_array, pr->id) = device; | ||
| 814 | |||
| 815 | per_cpu(processors, pr->id) = pr; | ||
| 816 | |||
| 817 | result = acpi_processor_add_fs(device); | ||
| 818 | if (result) | ||
| 819 | goto err_free_cpumask; | ||
| 820 | |||
| 821 | sysdev = get_cpu_sysdev(pr->id); | ||
| 822 | if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { | ||
| 823 | result = -EFAULT; | ||
| 824 | goto err_remove_fs; | ||
| 825 | } | ||
| 826 | |||
| 827 | /* _PDC call should be done before doing anything else (if reqd.). */ | ||
| 828 | arch_acpi_processor_init_pdc(pr); | ||
| 829 | acpi_processor_set_pdc(pr); | ||
| 830 | arch_acpi_processor_cleanup_pdc(pr); | ||
| 831 | |||
| 832 | #ifdef CONFIG_CPU_FREQ | ||
| 833 | acpi_processor_ppc_has_changed(pr); | ||
| 834 | #endif | ||
| 835 | acpi_processor_get_throttling_info(pr); | ||
| 836 | acpi_processor_get_limit_info(pr); | ||
| 837 | |||
| 838 | |||
| 839 | acpi_processor_power_init(pr, device); | ||
| 840 | |||
| 841 | pr->cdev = thermal_cooling_device_register("Processor", device, | ||
| 842 | &processor_cooling_ops); | ||
| 843 | if (IS_ERR(pr->cdev)) { | ||
| 844 | result = PTR_ERR(pr->cdev); | ||
| 845 | goto err_power_exit; | ||
| 846 | } | ||
| 847 | |||
| 848 | dev_info(&device->dev, "registered as cooling_device%d\n", | ||
| 849 | pr->cdev->id); | ||
| 850 | |||
| 851 | result = sysfs_create_link(&device->dev.kobj, | ||
| 852 | &pr->cdev->device.kobj, | ||
| 853 | "thermal_cooling"); | ||
| 854 | if (result) { | ||
| 855 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 856 | goto err_thermal_unregister; | ||
| 857 | } | ||
| 858 | result = sysfs_create_link(&pr->cdev->device.kobj, | ||
| 859 | &device->dev.kobj, | ||
| 860 | "device"); | ||
| 861 | if (result) { | ||
| 862 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 863 | goto err_remove_sysfs; | ||
| 864 | } | ||
| 865 | |||
| 866 | if (pr->flags.throttling) { | ||
| 867 | printk(KERN_INFO PREFIX "%s [%s] (supports", | ||
| 868 | acpi_device_name(device), acpi_device_bid(device)); | ||
| 869 | printk(" %d throttling states", pr->throttling.state_count); | ||
| 870 | printk(")\n"); | ||
| 871 | } | ||
| 872 | |||
| 868 | return 0; | 873 | return 0; |
| 874 | |||
| 875 | err_remove_sysfs: | ||
| 876 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); | ||
| 877 | err_thermal_unregister: | ||
| 878 | thermal_cooling_device_unregister(pr->cdev); | ||
| 879 | err_power_exit: | ||
| 880 | acpi_processor_power_exit(pr, device); | ||
| 881 | err_remove_fs: | ||
| 882 | acpi_processor_remove_fs(device); | ||
| 883 | err_free_cpumask: | ||
| 884 | free_cpumask_var(pr->throttling.shared_cpu_map); | ||
| 885 | |||
| 886 | return result; | ||
| 869 | } | 887 | } |
| 870 | 888 | ||
| 871 | static int acpi_processor_remove(struct acpi_device *device, int type) | 889 | static int acpi_processor_remove(struct acpi_device *device, int type) |
| @@ -942,7 +960,6 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) | |||
| 942 | { | 960 | { |
| 943 | acpi_handle phandle; | 961 | acpi_handle phandle; |
| 944 | struct acpi_device *pdev; | 962 | struct acpi_device *pdev; |
| 945 | struct acpi_processor *pr; | ||
| 946 | 963 | ||
| 947 | 964 | ||
| 948 | if (acpi_get_parent(handle, &phandle)) { | 965 | if (acpi_get_parent(handle, &phandle)) { |
| @@ -957,15 +974,6 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) | |||
| 957 | return -ENODEV; | 974 | return -ENODEV; |
| 958 | } | 975 | } |
| 959 | 976 | ||
| 960 | acpi_bus_start(*device); | ||
| 961 | |||
| 962 | pr = acpi_driver_data(*device); | ||
| 963 | if (!pr) | ||
| 964 | return -ENODEV; | ||
| 965 | |||
| 966 | if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) { | ||
| 967 | kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); | ||
| 968 | } | ||
| 969 | return 0; | 977 | return 0; |
| 970 | } | 978 | } |
| 971 | 979 | ||
| @@ -995,25 +1003,6 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle, | |||
| 995 | "Unable to add the device\n"); | 1003 | "Unable to add the device\n"); |
| 996 | break; | 1004 | break; |
| 997 | } | 1005 | } |
| 998 | |||
| 999 | pr = acpi_driver_data(device); | ||
| 1000 | if (!pr) { | ||
| 1001 | printk(KERN_ERR PREFIX "Driver data is NULL\n"); | ||
| 1002 | break; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | if (pr->id >= 0 && (pr->id < nr_cpu_ids)) { | ||
| 1006 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | ||
| 1007 | break; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | result = acpi_processor_start(device); | ||
| 1011 | if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) { | ||
| 1012 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | ||
| 1013 | } else { | ||
| 1014 | printk(KERN_ERR PREFIX "Device [%s] failed to start\n", | ||
| 1015 | acpi_device_bid(device)); | ||
| 1016 | } | ||
| 1017 | break; | 1006 | break; |
| 1018 | case ACPI_NOTIFY_EJECT_REQUEST: | 1007 | case ACPI_NOTIFY_EJECT_REQUEST: |
| 1019 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1008 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -1030,9 +1019,6 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle, | |||
| 1030 | "Driver data is NULL, dropping EJECT\n"); | 1019 | "Driver data is NULL, dropping EJECT\n"); |
| 1031 | return; | 1020 | return; |
| 1032 | } | 1021 | } |
| 1033 | |||
| 1034 | if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id))) | ||
| 1035 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | ||
| 1036 | break; | 1022 | break; |
| 1037 | default: | 1023 | default: |
| 1038 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 1024 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -1161,11 +1147,11 @@ static int __init acpi_processor_init(void) | |||
| 1161 | (struct acpi_table_header **)&madt))) | 1147 | (struct acpi_table_header **)&madt))) |
| 1162 | madt = NULL; | 1148 | madt = NULL; |
| 1163 | #endif | 1149 | #endif |
| 1164 | 1150 | #ifdef CONFIG_ACPI_PROCFS | |
| 1165 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 1151 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
| 1166 | if (!acpi_processor_dir) | 1152 | if (!acpi_processor_dir) |
| 1167 | return -ENOMEM; | 1153 | return -ENOMEM; |
| 1168 | 1154 | #endif | |
| 1169 | /* | 1155 | /* |
| 1170 | * Check whether the system is DMI table. If yes, OSPM | 1156 | * Check whether the system is DMI table. If yes, OSPM |
| 1171 | * should not use mwait for CPU-states. | 1157 | * should not use mwait for CPU-states. |
| @@ -1193,7 +1179,9 @@ out_cpuidle: | |||
| 1193 | cpuidle_unregister_driver(&acpi_idle_driver); | 1179 | cpuidle_unregister_driver(&acpi_idle_driver); |
| 1194 | 1180 | ||
| 1195 | out_proc: | 1181 | out_proc: |
| 1182 | #ifdef CONFIG_ACPI_PROCFS | ||
| 1196 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 1183 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
| 1184 | #endif | ||
| 1197 | 1185 | ||
| 1198 | return result; | 1186 | return result; |
| 1199 | } | 1187 | } |
| @@ -1213,7 +1201,9 @@ static void __exit acpi_processor_exit(void) | |||
| 1213 | 1201 | ||
| 1214 | cpuidle_unregister_driver(&acpi_idle_driver); | 1202 | cpuidle_unregister_driver(&acpi_idle_driver); |
| 1215 | 1203 | ||
| 1204 | #ifdef CONFIG_ACPI_PROCFS | ||
| 1216 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 1205 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
| 1206 | #endif | ||
| 1217 | 1207 | ||
| 1218 | return; | 1208 | return; |
| 1219 | } | 1209 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 66393d5c4c7c..cc61a6220102 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -60,6 +60,8 @@ | |||
| 60 | #include <acpi/processor.h> | 60 | #include <acpi/processor.h> |
| 61 | #include <asm/processor.h> | 61 | #include <asm/processor.h> |
| 62 | 62 | ||
| 63 | #define PREFIX "ACPI: " | ||
| 64 | |||
| 63 | #define ACPI_PROCESSOR_CLASS "processor" | 65 | #define ACPI_PROCESSOR_CLASS "processor" |
| 64 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 66 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 65 | ACPI_MODULE_NAME("processor_idle"); | 67 | ACPI_MODULE_NAME("processor_idle"); |
| @@ -680,6 +682,7 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) | |||
| 680 | return 0; | 682 | return 0; |
| 681 | } | 683 | } |
| 682 | 684 | ||
| 685 | #ifdef CONFIG_ACPI_PROCFS | ||
| 683 | static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) | 686 | static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) |
| 684 | { | 687 | { |
| 685 | struct acpi_processor *pr = seq->private; | 688 | struct acpi_processor *pr = seq->private; |
| @@ -759,7 +762,7 @@ static const struct file_operations acpi_processor_power_fops = { | |||
| 759 | .llseek = seq_lseek, | 762 | .llseek = seq_lseek, |
| 760 | .release = single_release, | 763 | .release = single_release, |
| 761 | }; | 764 | }; |
| 762 | 765 | #endif | |
| 763 | 766 | ||
| 764 | /** | 767 | /** |
| 765 | * acpi_idle_bm_check - checks if bus master activity was detected | 768 | * acpi_idle_bm_check - checks if bus master activity was detected |
| @@ -1160,7 +1163,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
| 1160 | { | 1163 | { |
| 1161 | acpi_status status = 0; | 1164 | acpi_status status = 0; |
| 1162 | static int first_run; | 1165 | static int first_run; |
| 1166 | #ifdef CONFIG_ACPI_PROCFS | ||
| 1163 | struct proc_dir_entry *entry = NULL; | 1167 | struct proc_dir_entry *entry = NULL; |
| 1168 | #endif | ||
| 1164 | unsigned int i; | 1169 | unsigned int i; |
| 1165 | 1170 | ||
| 1166 | if (boot_option_idle_override) | 1171 | if (boot_option_idle_override) |
| @@ -1217,7 +1222,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
| 1217 | pr->power.states[i].type); | 1222 | pr->power.states[i].type); |
| 1218 | printk(")\n"); | 1223 | printk(")\n"); |
| 1219 | } | 1224 | } |
| 1220 | 1225 | #ifdef CONFIG_ACPI_PROCFS | |
| 1221 | /* 'power' [R] */ | 1226 | /* 'power' [R] */ |
| 1222 | entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER, | 1227 | entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER, |
| 1223 | S_IRUGO, acpi_device_dir(device), | 1228 | S_IRUGO, acpi_device_dir(device), |
| @@ -1225,6 +1230,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
| 1225 | acpi_driver_data(device)); | 1230 | acpi_driver_data(device)); |
| 1226 | if (!entry) | 1231 | if (!entry) |
| 1227 | return -EIO; | 1232 | return -EIO; |
| 1233 | #endif | ||
| 1228 | return 0; | 1234 | return 0; |
| 1229 | } | 1235 | } |
| 1230 | 1236 | ||
| @@ -1237,9 +1243,11 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
| 1237 | cpuidle_unregister_device(&pr->power.dev); | 1243 | cpuidle_unregister_device(&pr->power.dev); |
| 1238 | pr->flags.power_setup_done = 0; | 1244 | pr->flags.power_setup_done = 0; |
| 1239 | 1245 | ||
| 1246 | #ifdef CONFIG_ACPI_PROCFS | ||
| 1240 | if (acpi_device_dir(device)) | 1247 | if (acpi_device_dir(device)) |
| 1241 | remove_proc_entry(ACPI_PROCESSOR_FILE_POWER, | 1248 | remove_proc_entry(ACPI_PROCESSOR_FILE_POWER, |
| 1242 | acpi_device_dir(device)); | 1249 | acpi_device_dir(device)); |
| 1250 | #endif | ||
| 1243 | 1251 | ||
| 1244 | return 0; | 1252 | return 0; |
| 1245 | } | 1253 | } |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 60e543d3234e..11088cf10319 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -39,6 +39,8 @@ | |||
| 39 | #include <acpi/acpi_drivers.h> | 39 | #include <acpi/acpi_drivers.h> |
| 40 | #include <acpi/processor.h> | 40 | #include <acpi/processor.h> |
| 41 | 41 | ||
| 42 | #define PREFIX "ACPI: " | ||
| 43 | |||
| 42 | #define ACPI_PROCESSOR_CLASS "processor" | 44 | #define ACPI_PROCESSOR_CLASS "processor" |
| 43 | #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" | 45 | #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" |
| 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 46 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 31adda1099e0..140c5c5b423c 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #include <acpi/processor.h> | 40 | #include <acpi/processor.h> |
| 41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
| 42 | 42 | ||
| 43 | #define PREFIX "ACPI: " | ||
| 44 | |||
| 43 | #define ACPI_PROCESSOR_CLASS "processor" | 45 | #define ACPI_PROCESSOR_CLASS "processor" |
| 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 46 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 45 | ACPI_MODULE_NAME("processor_thermal"); | 47 | ACPI_MODULE_NAME("processor_thermal"); |
| @@ -438,7 +440,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { | |||
| 438 | }; | 440 | }; |
| 439 | 441 | ||
| 440 | /* /proc interface */ | 442 | /* /proc interface */ |
| 441 | 443 | #ifdef CONFIG_ACPI_PROCFS | |
| 442 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) | 444 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) |
| 443 | { | 445 | { |
| 444 | struct acpi_processor *pr = (struct acpi_processor *)seq->private; | 446 | struct acpi_processor *pr = (struct acpi_processor *)seq->private; |
| @@ -517,3 +519,4 @@ const struct file_operations acpi_processor_limit_fops = { | |||
| 517 | .llseek = seq_lseek, | 519 | .llseek = seq_lseek, |
| 518 | .release = single_release, | 520 | .release = single_release, |
| 519 | }; | 521 | }; |
| 522 | #endif | ||
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index ae39797aab55..ce7cf3bc5101 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -41,6 +41,8 @@ | |||
| 41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
| 42 | #include <acpi/processor.h> | 42 | #include <acpi/processor.h> |
| 43 | 43 | ||
| 44 | #define PREFIX "ACPI: " | ||
| 45 | |||
| 44 | #define ACPI_PROCESSOR_CLASS "processor" | 46 | #define ACPI_PROCESSOR_CLASS "processor" |
| 45 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 47 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 46 | ACPI_MODULE_NAME("processor_throttling"); | 48 | ACPI_MODULE_NAME("processor_throttling"); |
| @@ -1216,7 +1218,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
| 1216 | } | 1218 | } |
| 1217 | 1219 | ||
| 1218 | /* proc interface */ | 1220 | /* proc interface */ |
| 1219 | 1221 | #ifdef CONFIG_ACPI_PROCFS | |
| 1220 | static int acpi_processor_throttling_seq_show(struct seq_file *seq, | 1222 | static int acpi_processor_throttling_seq_show(struct seq_file *seq, |
| 1221 | void *offset) | 1223 | void *offset) |
| 1222 | { | 1224 | { |
| @@ -1324,3 +1326,4 @@ const struct file_operations acpi_processor_throttling_fops = { | |||
| 1324 | .llseek = seq_lseek, | 1326 | .llseek = seq_lseek, |
| 1325 | .release = single_release, | 1327 | .release = single_release, |
| 1326 | }; | 1328 | }; |
| 1329 | #endif | ||
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 4b214b74ebaa..52b9db8afc20 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
| @@ -46,6 +46,8 @@ | |||
| 46 | 46 | ||
| 47 | #include "sbshc.h" | 47 | #include "sbshc.h" |
| 48 | 48 | ||
| 49 | #define PREFIX "ACPI: " | ||
| 50 | |||
| 49 | #define ACPI_SBS_CLASS "sbs" | 51 | #define ACPI_SBS_CLASS "sbs" |
| 50 | #define ACPI_AC_CLASS "ac_adapter" | 52 | #define ACPI_AC_CLASS "ac_adapter" |
| 51 | #define ACPI_BATTERY_CLASS "battery" | 53 | #define ACPI_BATTERY_CLASS "battery" |
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 0619734895b2..d9339806df45 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include "sbshc.h" | 16 | #include "sbshc.h" |
| 17 | 17 | ||
| 18 | #define PREFIX "ACPI: " | ||
| 19 | |||
| 18 | #define ACPI_SMB_HC_CLASS "smbus_host_controller" | 20 | #define ACPI_SMB_HC_CLASS "smbus_host_controller" |
| 19 | #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" | 21 | #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" |
| 20 | 22 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 318b1ea7a5bf..408ebde18986 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -60,13 +60,13 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | if (acpi_dev->flags.compatible_ids) { | 62 | if (acpi_dev->flags.compatible_ids) { |
| 63 | struct acpi_compatible_id_list *cid_list; | 63 | struct acpica_device_id_list *cid_list; |
| 64 | int i; | 64 | int i; |
| 65 | 65 | ||
| 66 | cid_list = acpi_dev->pnp.cid_list; | 66 | cid_list = acpi_dev->pnp.cid_list; |
| 67 | for (i = 0; i < cid_list->count; i++) { | 67 | for (i = 0; i < cid_list->count; i++) { |
| 68 | count = snprintf(&modalias[len], size, "%s:", | 68 | count = snprintf(&modalias[len], size, "%s:", |
| 69 | cid_list->id[i].value); | 69 | cid_list->ids[i].string); |
| 70 | if (count < 0 || count >= size) { | 70 | if (count < 0 || count >= size) { |
| 71 | printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", | 71 | printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", |
| 72 | acpi_dev->pnp.device_name, i); | 72 | acpi_dev->pnp.device_name, i); |
| @@ -287,14 +287,14 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | if (device->flags.compatible_ids) { | 289 | if (device->flags.compatible_ids) { |
| 290 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; | 290 | struct acpica_device_id_list *cid_list = device->pnp.cid_list; |
| 291 | int i; | 291 | int i; |
| 292 | 292 | ||
| 293 | for (id = ids; id->id[0]; id++) { | 293 | for (id = ids; id->id[0]; id++) { |
| 294 | /* compare multiple _CID entries against driver ids */ | 294 | /* compare multiple _CID entries against driver ids */ |
| 295 | for (i = 0; i < cid_list->count; i++) { | 295 | for (i = 0; i < cid_list->count; i++) { |
| 296 | if (!strcmp((char*)id->id, | 296 | if (!strcmp((char*)id->id, |
| 297 | cid_list->id[i].value)) | 297 | cid_list->ids[i].string)) |
| 298 | return 0; | 298 | return 0; |
| 299 | } | 299 | } |
| 300 | } | 300 | } |
| @@ -309,6 +309,10 @@ static void acpi_device_release(struct device *dev) | |||
| 309 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 309 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
| 310 | 310 | ||
| 311 | kfree(acpi_dev->pnp.cid_list); | 311 | kfree(acpi_dev->pnp.cid_list); |
| 312 | if (acpi_dev->flags.hardware_id) | ||
| 313 | kfree(acpi_dev->pnp.hardware_id); | ||
| 314 | if (acpi_dev->flags.unique_id) | ||
| 315 | kfree(acpi_dev->pnp.unique_id); | ||
| 312 | kfree(acpi_dev); | 316 | kfree(acpi_dev); |
| 313 | } | 317 | } |
| 314 | 318 | ||
| @@ -366,7 +370,8 @@ static acpi_status acpi_device_notify_fixed(void *data) | |||
| 366 | { | 370 | { |
| 367 | struct acpi_device *device = data; | 371 | struct acpi_device *device = data; |
| 368 | 372 | ||
| 369 | acpi_device_notify(device->handle, ACPI_FIXED_HARDWARE_EVENT, device); | 373 | /* Fixed hardware devices have no handles */ |
| 374 | acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); | ||
| 370 | return AE_OK; | 375 | return AE_OK; |
| 371 | } | 376 | } |
| 372 | 377 | ||
| @@ -426,9 +431,6 @@ static int acpi_device_probe(struct device * dev) | |||
| 426 | if (acpi_drv->ops.notify) { | 431 | if (acpi_drv->ops.notify) { |
| 427 | ret = acpi_device_install_notify_handler(acpi_dev); | 432 | ret = acpi_device_install_notify_handler(acpi_dev); |
| 428 | if (ret) { | 433 | if (ret) { |
| 429 | if (acpi_drv->ops.stop) | ||
| 430 | acpi_drv->ops.stop(acpi_dev, | ||
| 431 | acpi_dev->removal_type); | ||
| 432 | if (acpi_drv->ops.remove) | 434 | if (acpi_drv->ops.remove) |
| 433 | acpi_drv->ops.remove(acpi_dev, | 435 | acpi_drv->ops.remove(acpi_dev, |
| 434 | acpi_dev->removal_type); | 436 | acpi_dev->removal_type); |
| @@ -452,8 +454,6 @@ static int acpi_device_remove(struct device * dev) | |||
| 452 | if (acpi_drv) { | 454 | if (acpi_drv) { |
| 453 | if (acpi_drv->ops.notify) | 455 | if (acpi_drv->ops.notify) |
| 454 | acpi_device_remove_notify_handler(acpi_dev); | 456 | acpi_device_remove_notify_handler(acpi_dev); |
| 455 | if (acpi_drv->ops.stop) | ||
| 456 | acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type); | ||
| 457 | if (acpi_drv->ops.remove) | 457 | if (acpi_drv->ops.remove) |
| 458 | acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); | 458 | acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); |
| 459 | } | 459 | } |
| @@ -687,7 +687,7 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) | |||
| 687 | } | 687 | } |
| 688 | EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); | 688 | EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); |
| 689 | 689 | ||
| 690 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) | 690 | void acpi_bus_data_handler(acpi_handle handle, void *context) |
| 691 | { | 691 | { |
| 692 | 692 | ||
| 693 | /* TBD */ | 693 | /* TBD */ |
| @@ -1000,33 +1000,89 @@ static int acpi_dock_match(struct acpi_device *device) | |||
| 1000 | return acpi_get_handle(device->handle, "_DCK", &tmp); | 1000 | return acpi_get_handle(device->handle, "_DCK", &tmp); |
| 1001 | } | 1001 | } |
| 1002 | 1002 | ||
| 1003 | static struct acpica_device_id_list* | ||
| 1004 | acpi_add_cid( | ||
| 1005 | struct acpi_device_info *info, | ||
| 1006 | struct acpica_device_id *new_cid) | ||
| 1007 | { | ||
| 1008 | struct acpica_device_id_list *cid; | ||
| 1009 | char *next_id_string; | ||
| 1010 | acpi_size cid_length; | ||
| 1011 | acpi_size new_cid_length; | ||
| 1012 | u32 i; | ||
| 1013 | |||
| 1014 | |||
| 1015 | /* Allocate new CID list with room for the new CID */ | ||
| 1016 | |||
| 1017 | if (!new_cid) | ||
| 1018 | new_cid_length = info->compatible_id_list.list_size; | ||
| 1019 | else if (info->compatible_id_list.list_size) | ||
| 1020 | new_cid_length = info->compatible_id_list.list_size + | ||
| 1021 | new_cid->length + sizeof(struct acpica_device_id); | ||
| 1022 | else | ||
| 1023 | new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length; | ||
| 1024 | |||
| 1025 | cid = ACPI_ALLOCATE_ZEROED(new_cid_length); | ||
| 1026 | if (!cid) { | ||
| 1027 | return NULL; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | cid->list_size = new_cid_length; | ||
| 1031 | cid->count = info->compatible_id_list.count; | ||
| 1032 | if (new_cid) | ||
| 1033 | cid->count++; | ||
| 1034 | next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id)); | ||
| 1035 | |||
| 1036 | /* Copy all existing CIDs */ | ||
| 1037 | |||
| 1038 | for (i = 0; i < info->compatible_id_list.count; i++) { | ||
| 1039 | cid_length = info->compatible_id_list.ids[i].length; | ||
| 1040 | cid->ids[i].string = next_id_string; | ||
| 1041 | cid->ids[i].length = cid_length; | ||
| 1042 | |||
| 1043 | ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string, | ||
| 1044 | cid_length); | ||
| 1045 | |||
| 1046 | next_id_string += cid_length; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | /* Append the new CID */ | ||
| 1050 | |||
| 1051 | if (new_cid) { | ||
| 1052 | cid->ids[i].string = next_id_string; | ||
| 1053 | cid->ids[i].length = new_cid->length; | ||
| 1054 | |||
| 1055 | ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | return cid; | ||
| 1059 | } | ||
| 1060 | |||
| 1003 | static void acpi_device_set_id(struct acpi_device *device, | 1061 | static void acpi_device_set_id(struct acpi_device *device, |
| 1004 | struct acpi_device *parent, acpi_handle handle, | 1062 | struct acpi_device *parent, acpi_handle handle, |
| 1005 | int type) | 1063 | int type) |
| 1006 | { | 1064 | { |
| 1007 | struct acpi_device_info *info; | 1065 | struct acpi_device_info *info = NULL; |
| 1008 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 1009 | char *hid = NULL; | 1066 | char *hid = NULL; |
| 1010 | char *uid = NULL; | 1067 | char *uid = NULL; |
| 1011 | struct acpi_compatible_id_list *cid_list = NULL; | 1068 | struct acpica_device_id_list *cid_list = NULL; |
| 1012 | const char *cid_add = NULL; | 1069 | char *cid_add = NULL; |
| 1013 | acpi_status status; | 1070 | acpi_status status; |
| 1014 | 1071 | ||
| 1015 | switch (type) { | 1072 | switch (type) { |
| 1016 | case ACPI_BUS_TYPE_DEVICE: | 1073 | case ACPI_BUS_TYPE_DEVICE: |
| 1017 | status = acpi_get_object_info(handle, &buffer); | 1074 | status = acpi_get_object_info(handle, &info); |
| 1018 | if (ACPI_FAILURE(status)) { | 1075 | if (ACPI_FAILURE(status)) { |
| 1019 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); | 1076 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); |
| 1020 | return; | 1077 | return; |
| 1021 | } | 1078 | } |
| 1022 | 1079 | ||
| 1023 | info = buffer.pointer; | ||
| 1024 | if (info->valid & ACPI_VALID_HID) | 1080 | if (info->valid & ACPI_VALID_HID) |
| 1025 | hid = info->hardware_id.value; | 1081 | hid = info->hardware_id.string; |
| 1026 | if (info->valid & ACPI_VALID_UID) | 1082 | if (info->valid & ACPI_VALID_UID) |
| 1027 | uid = info->unique_id.value; | 1083 | uid = info->unique_id.string; |
| 1028 | if (info->valid & ACPI_VALID_CID) | 1084 | if (info->valid & ACPI_VALID_CID) |
| 1029 | cid_list = &info->compatibility_id; | 1085 | cid_list = &info->compatible_id_list; |
| 1030 | if (info->valid & ACPI_VALID_ADR) { | 1086 | if (info->valid & ACPI_VALID_ADR) { |
| 1031 | device->pnp.bus_address = info->address; | 1087 | device->pnp.bus_address = info->address; |
| 1032 | device->flags.bus_address = 1; | 1088 | device->flags.bus_address = 1; |
| @@ -1077,55 +1133,46 @@ static void acpi_device_set_id(struct acpi_device *device, | |||
| 1077 | } | 1133 | } |
| 1078 | 1134 | ||
| 1079 | if (hid) { | 1135 | if (hid) { |
| 1080 | strcpy(device->pnp.hardware_id, hid); | 1136 | device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1); |
| 1081 | device->flags.hardware_id = 1; | 1137 | if (device->pnp.hardware_id) { |
| 1138 | strcpy(device->pnp.hardware_id, hid); | ||
| 1139 | device->flags.hardware_id = 1; | ||
| 1140 | } | ||
| 1082 | } | 1141 | } |
| 1142 | if (!device->flags.hardware_id) | ||
| 1143 | device->pnp.hardware_id = ""; | ||
| 1144 | |||
| 1083 | if (uid) { | 1145 | if (uid) { |
| 1084 | strcpy(device->pnp.unique_id, uid); | 1146 | device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); |
| 1085 | device->flags.unique_id = 1; | 1147 | if (device->pnp.unique_id) { |
| 1148 | strcpy(device->pnp.unique_id, uid); | ||
| 1149 | device->flags.unique_id = 1; | ||
| 1150 | } | ||
| 1086 | } | 1151 | } |
| 1152 | if (!device->flags.unique_id) | ||
| 1153 | device->pnp.unique_id = ""; | ||
| 1154 | |||
| 1087 | if (cid_list || cid_add) { | 1155 | if (cid_list || cid_add) { |
| 1088 | struct acpi_compatible_id_list *list; | 1156 | struct acpica_device_id_list *list; |
| 1089 | int size = 0; | 1157 | |
| 1090 | int count = 0; | 1158 | if (cid_add) { |
| 1091 | 1159 | struct acpica_device_id cid; | |
| 1092 | if (cid_list) { | 1160 | cid.length = strlen (cid_add) + 1; |
| 1093 | size = cid_list->size; | 1161 | cid.string = cid_add; |
| 1094 | } else if (cid_add) { | 1162 | |
| 1095 | size = sizeof(struct acpi_compatible_id_list); | 1163 | list = acpi_add_cid(info, &cid); |
| 1096 | cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); | 1164 | } else { |
| 1097 | if (!cid_list) { | 1165 | list = acpi_add_cid(info, NULL); |
| 1098 | printk(KERN_ERR "Memory allocation error\n"); | ||
| 1099 | kfree(buffer.pointer); | ||
| 1100 | return; | ||
| 1101 | } else { | ||
| 1102 | cid_list->count = 0; | ||
| 1103 | cid_list->size = size; | ||
| 1104 | } | ||
| 1105 | } | 1166 | } |
| 1106 | if (cid_add) | ||
| 1107 | size += sizeof(struct acpi_compatible_id); | ||
| 1108 | list = kmalloc(size, GFP_KERNEL); | ||
| 1109 | 1167 | ||
| 1110 | if (list) { | 1168 | if (list) { |
| 1111 | if (cid_list) { | ||
| 1112 | memcpy(list, cid_list, cid_list->size); | ||
| 1113 | count = cid_list->count; | ||
| 1114 | } | ||
| 1115 | if (cid_add) { | ||
| 1116 | strncpy(list->id[count].value, cid_add, | ||
| 1117 | ACPI_MAX_CID_LENGTH); | ||
| 1118 | count++; | ||
| 1119 | device->flags.compatible_ids = 1; | ||
| 1120 | } | ||
| 1121 | list->size = size; | ||
| 1122 | list->count = count; | ||
| 1123 | device->pnp.cid_list = list; | 1169 | device->pnp.cid_list = list; |
| 1124 | } else | 1170 | if (cid_add) |
| 1125 | printk(KERN_ERR PREFIX "Memory allocation error\n"); | 1171 | device->flags.compatible_ids = 1; |
| 1172 | } | ||
| 1126 | } | 1173 | } |
| 1127 | 1174 | ||
| 1128 | kfree(buffer.pointer); | 1175 | kfree(info); |
| 1129 | } | 1176 | } |
| 1130 | 1177 | ||
| 1131 | static int acpi_device_set_context(struct acpi_device *device, int type) | 1178 | static int acpi_device_set_context(struct acpi_device *device, int type) |
| @@ -1265,16 +1312,6 @@ acpi_add_single_object(struct acpi_device **child, | |||
| 1265 | acpi_device_set_id(device, parent, handle, type); | 1312 | acpi_device_set_id(device, parent, handle, type); |
| 1266 | 1313 | ||
| 1267 | /* | 1314 | /* |
| 1268 | * The ACPI device is attached to acpi handle before getting | ||
| 1269 | * the power/wakeup/peformance flags. Otherwise OS can't get | ||
| 1270 | * the corresponding ACPI device by the acpi handle in the course | ||
| 1271 | * of getting the power/wakeup/performance flags. | ||
| 1272 | */ | ||
| 1273 | result = acpi_device_set_context(device, type); | ||
| 1274 | if (result) | ||
| 1275 | goto end; | ||
| 1276 | |||
| 1277 | /* | ||
| 1278 | * Power Management | 1315 | * Power Management |
| 1279 | * ---------------- | 1316 | * ---------------- |
| 1280 | */ | 1317 | */ |
| @@ -1304,6 +1341,8 @@ acpi_add_single_object(struct acpi_device **child, | |||
| 1304 | goto end; | 1341 | goto end; |
| 1305 | } | 1342 | } |
| 1306 | 1343 | ||
| 1344 | if ((result = acpi_device_set_context(device, type))) | ||
| 1345 | goto end; | ||
| 1307 | 1346 | ||
| 1308 | result = acpi_device_register(device, parent); | 1347 | result = acpi_device_register(device, parent); |
| 1309 | 1348 | ||
| @@ -1318,10 +1357,8 @@ acpi_add_single_object(struct acpi_device **child, | |||
| 1318 | end: | 1357 | end: |
| 1319 | if (!result) | 1358 | if (!result) |
| 1320 | *child = device; | 1359 | *child = device; |
| 1321 | else { | 1360 | else |
| 1322 | kfree(device->pnp.cid_list); | 1361 | acpi_device_release(&device->dev); |
| 1323 | kfree(device); | ||
| 1324 | } | ||
| 1325 | 1362 | ||
| 1326 | return result; | 1363 | return result; |
| 1327 | } | 1364 | } |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index feece693d773..a90afcc723ab 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -405,6 +405,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 405 | }, | 405 | }, |
| 406 | }, | 406 | }, |
| 407 | { | 407 | { |
| 408 | .callback = init_set_sci_en_on_resume, | ||
| 409 | .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC", | ||
| 410 | .matches = { | ||
| 411 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 412 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"), | ||
| 413 | }, | ||
| 414 | }, | ||
| 415 | { | ||
| 408 | .callback = init_old_suspend_ordering, | 416 | .callback = init_old_suspend_ordering, |
| 409 | .ident = "Panasonic CF51-2L", | 417 | .ident = "Panasonic CF51-2L", |
| 410 | .matches = { | 418 | .matches = { |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 9c61ab2177cf..d11282975f35 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | 31 | ||
| 32 | #include <acpi/acpi_drivers.h> | 32 | #include <acpi/acpi_drivers.h> |
| 33 | 33 | ||
| 34 | #define PREFIX "ACPI: " | ||
| 35 | |||
| 34 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 36 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
| 35 | ACPI_MODULE_NAME("system"); | 37 | ACPI_MODULE_NAME("system"); |
| 36 | 38 | ||
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 646d39c031ca..f336bca7c450 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
| @@ -213,6 +213,9 @@ acpi_table_parse_entries(char *id, | |||
| 213 | unsigned long table_end; | 213 | unsigned long table_end; |
| 214 | acpi_size tbl_size; | 214 | acpi_size tbl_size; |
| 215 | 215 | ||
| 216 | if (acpi_disabled) | ||
| 217 | return -ENODEV; | ||
| 218 | |||
| 216 | if (!handler) | 219 | if (!handler) |
| 217 | return -EINVAL; | 220 | return -EINVAL; |
| 218 | 221 | ||
| @@ -277,6 +280,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) | |||
| 277 | struct acpi_table_header *table = NULL; | 280 | struct acpi_table_header *table = NULL; |
| 278 | acpi_size tbl_size; | 281 | acpi_size tbl_size; |
| 279 | 282 | ||
| 283 | if (acpi_disabled) | ||
| 284 | return -ENODEV; | ||
| 285 | |||
| 280 | if (!handler) | 286 | if (!handler) |
| 281 | return -EINVAL; | 287 | return -EINVAL; |
| 282 | 288 | ||
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 564ea1424288..65f67815902a 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
| @@ -47,6 +47,8 @@ | |||
| 47 | #include <acpi/acpi_bus.h> | 47 | #include <acpi/acpi_bus.h> |
| 48 | #include <acpi/acpi_drivers.h> | 48 | #include <acpi/acpi_drivers.h> |
| 49 | 49 | ||
| 50 | #define PREFIX "ACPI: " | ||
| 51 | |||
| 50 | #define ACPI_THERMAL_CLASS "thermal_zone" | 52 | #define ACPI_THERMAL_CLASS "thermal_zone" |
| 51 | #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" | 53 | #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" |
| 52 | #define ACPI_THERMAL_FILE_STATE "state" | 54 | #define ACPI_THERMAL_FILE_STATE "state" |
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index f844941089bb..811fec10462b 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | #include <acpi/acpi_bus.h> | 30 | #include <acpi/acpi_bus.h> |
| 31 | #include <acpi/acpi_drivers.h> | 31 | #include <acpi/acpi_drivers.h> |
| 32 | 32 | ||
| 33 | #include "internal.h" | ||
| 34 | |||
| 33 | #define _COMPONENT ACPI_BUS_COMPONENT | 35 | #define _COMPONENT ACPI_BUS_COMPONENT |
| 34 | ACPI_MODULE_NAME("utils"); | 36 | ACPI_MODULE_NAME("utils"); |
| 35 | 37 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 60ea984c84a0..94b1a4c5abab 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -40,10 +40,12 @@ | |||
| 40 | #include <linux/pci.h> | 40 | #include <linux/pci.h> |
| 41 | #include <linux/pci_ids.h> | 41 | #include <linux/pci_ids.h> |
| 42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
| 43 | 43 | #include <linux/dmi.h> | |
| 44 | #include <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
| 45 | #include <acpi/acpi_drivers.h> | 45 | #include <acpi/acpi_drivers.h> |
| 46 | 46 | ||
| 47 | #define PREFIX "ACPI: " | ||
| 48 | |||
| 47 | #define ACPI_VIDEO_CLASS "video" | 49 | #define ACPI_VIDEO_CLASS "video" |
| 48 | #define ACPI_VIDEO_BUS_NAME "Video Bus" | 50 | #define ACPI_VIDEO_BUS_NAME "Video Bus" |
| 49 | #define ACPI_VIDEO_DEVICE_NAME "Video Device" | 51 | #define ACPI_VIDEO_DEVICE_NAME "Video Device" |
| @@ -198,7 +200,7 @@ struct acpi_video_device { | |||
| 198 | struct acpi_device *dev; | 200 | struct acpi_device *dev; |
| 199 | struct acpi_video_device_brightness *brightness; | 201 | struct acpi_video_device_brightness *brightness; |
| 200 | struct backlight_device *backlight; | 202 | struct backlight_device *backlight; |
| 201 | struct thermal_cooling_device *cdev; | 203 | struct thermal_cooling_device *cooling_dev; |
| 202 | struct output_device *output_dev; | 204 | struct output_device *output_dev; |
| 203 | }; | 205 | }; |
| 204 | 206 | ||
| @@ -387,20 +389,20 @@ static struct output_properties acpi_output_properties = { | |||
| 387 | 389 | ||
| 388 | 390 | ||
| 389 | /* thermal cooling device callbacks */ | 391 | /* thermal cooling device callbacks */ |
| 390 | static int video_get_max_state(struct thermal_cooling_device *cdev, unsigned | 392 | static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned |
| 391 | long *state) | 393 | long *state) |
| 392 | { | 394 | { |
| 393 | struct acpi_device *device = cdev->devdata; | 395 | struct acpi_device *device = cooling_dev->devdata; |
| 394 | struct acpi_video_device *video = acpi_driver_data(device); | 396 | struct acpi_video_device *video = acpi_driver_data(device); |
| 395 | 397 | ||
| 396 | *state = video->brightness->count - 3; | 398 | *state = video->brightness->count - 3; |
| 397 | return 0; | 399 | return 0; |
| 398 | } | 400 | } |
| 399 | 401 | ||
| 400 | static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned | 402 | static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsigned |
| 401 | long *state) | 403 | long *state) |
| 402 | { | 404 | { |
| 403 | struct acpi_device *device = cdev->devdata; | 405 | struct acpi_device *device = cooling_dev->devdata; |
| 404 | struct acpi_video_device *video = acpi_driver_data(device); | 406 | struct acpi_video_device *video = acpi_driver_data(device); |
| 405 | unsigned long long level; | 407 | unsigned long long level; |
| 406 | int offset; | 408 | int offset; |
| @@ -417,9 +419,9 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned | |||
| 417 | } | 419 | } |
| 418 | 420 | ||
| 419 | static int | 421 | static int |
| 420 | video_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) | 422 | video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state) |
| 421 | { | 423 | { |
| 422 | struct acpi_device *device = cdev->devdata; | 424 | struct acpi_device *device = cooling_dev->devdata; |
| 423 | struct acpi_video_device *video = acpi_driver_data(device); | 425 | struct acpi_video_device *video = acpi_driver_data(device); |
| 424 | int level; | 426 | int level; |
| 425 | 427 | ||
| @@ -603,6 +605,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | |||
| 603 | unsigned long long *level) | 605 | unsigned long long *level) |
| 604 | { | 606 | { |
| 605 | acpi_status status = AE_OK; | 607 | acpi_status status = AE_OK; |
| 608 | int i; | ||
| 606 | 609 | ||
| 607 | if (device->cap._BQC || device->cap._BCQ) { | 610 | if (device->cap._BQC || device->cap._BCQ) { |
| 608 | char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; | 611 | char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; |
| @@ -618,8 +621,15 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | |||
| 618 | 621 | ||
| 619 | } | 622 | } |
| 620 | *level += bqc_offset_aml_bug_workaround; | 623 | *level += bqc_offset_aml_bug_workaround; |
| 621 | device->brightness->curr = *level; | 624 | for (i = 2; i < device->brightness->count; i++) |
| 622 | return 0; | 625 | if (device->brightness->levels[i] == *level) { |
| 626 | device->brightness->curr = *level; | ||
| 627 | return 0; | ||
| 628 | } | ||
| 629 | /* BQC returned an invalid level. Stop using it. */ | ||
| 630 | ACPI_WARNING((AE_INFO, "%s returned an invalid level", | ||
| 631 | buf)); | ||
| 632 | device->cap._BQC = device->cap._BCQ = 0; | ||
| 623 | } else { | 633 | } else { |
| 624 | /* Fixme: | 634 | /* Fixme: |
| 625 | * should we return an error or ignore this failure? | 635 | * should we return an error or ignore this failure? |
| @@ -870,7 +880,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
| 870 | br->flags._BCM_use_index = br->flags._BCL_use_index; | 880 | br->flags._BCM_use_index = br->flags._BCL_use_index; |
| 871 | 881 | ||
| 872 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ | 882 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ |
| 873 | br->curr = level_old = max_level; | 883 | br->curr = level = max_level; |
| 874 | 884 | ||
| 875 | if (!device->cap._BQC) | 885 | if (!device->cap._BQC) |
| 876 | goto set_level; | 886 | goto set_level; |
| @@ -892,15 +902,25 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
| 892 | 902 | ||
| 893 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); | 903 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); |
| 894 | 904 | ||
| 895 | if (!br->flags._BQC_use_index) | 905 | if (!br->flags._BQC_use_index) { |
| 906 | /* | ||
| 907 | * Set the backlight to the initial state. | ||
| 908 | * On some buggy laptops, _BQC returns an uninitialized value | ||
| 909 | * when invoked for the first time, i.e. level_old is invalid. | ||
| 910 | * set the backlight to max_level in this case | ||
| 911 | */ | ||
| 912 | for (i = 2; i < br->count; i++) | ||
| 913 | if (level_old == br->levels[i]) | ||
| 914 | level = level_old; | ||
| 896 | goto set_level; | 915 | goto set_level; |
| 916 | } | ||
| 897 | 917 | ||
| 898 | if (br->flags._BCL_reversed) | 918 | if (br->flags._BCL_reversed) |
| 899 | level_old = (br->count - 1) - level_old; | 919 | level_old = (br->count - 1) - level_old; |
| 900 | level_old = br->levels[level_old]; | 920 | level = br->levels[level_old]; |
| 901 | 921 | ||
| 902 | set_level: | 922 | set_level: |
| 903 | result = acpi_video_device_lcd_set_level(device, level_old); | 923 | result = acpi_video_device_lcd_set_level(device, level); |
| 904 | if (result) | 924 | if (result) |
| 905 | goto out_free_levels; | 925 | goto out_free_levels; |
| 906 | 926 | ||
| @@ -934,9 +954,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 934 | { | 954 | { |
| 935 | acpi_handle h_dummy1; | 955 | acpi_handle h_dummy1; |
| 936 | 956 | ||
| 937 | |||
| 938 | memset(&device->cap, 0, sizeof(device->cap)); | ||
| 939 | |||
| 940 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { | 957 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { |
| 941 | device->cap._ADR = 1; | 958 | device->cap._ADR = 1; |
| 942 | } | 959 | } |
| @@ -990,19 +1007,29 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 990 | if (result) | 1007 | if (result) |
| 991 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1008 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
| 992 | 1009 | ||
| 993 | device->cdev = thermal_cooling_device_register("LCD", | 1010 | device->cooling_dev = thermal_cooling_device_register("LCD", |
| 994 | device->dev, &video_cooling_ops); | 1011 | device->dev, &video_cooling_ops); |
| 995 | if (IS_ERR(device->cdev)) | 1012 | if (IS_ERR(device->cooling_dev)) { |
| 1013 | /* | ||
| 1014 | * Set cooling_dev to NULL so we don't crash trying to | ||
| 1015 | * free it. | ||
| 1016 | * Also, why the hell we are returning early and | ||
| 1017 | * not attempt to register video output if cooling | ||
| 1018 | * device registration failed? | ||
| 1019 | * -- dtor | ||
| 1020 | */ | ||
| 1021 | device->cooling_dev = NULL; | ||
| 996 | return; | 1022 | return; |
| 1023 | } | ||
| 997 | 1024 | ||
| 998 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", | 1025 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", |
| 999 | device->cdev->id); | 1026 | device->cooling_dev->id); |
| 1000 | result = sysfs_create_link(&device->dev->dev.kobj, | 1027 | result = sysfs_create_link(&device->dev->dev.kobj, |
| 1001 | &device->cdev->device.kobj, | 1028 | &device->cooling_dev->device.kobj, |
| 1002 | "thermal_cooling"); | 1029 | "thermal_cooling"); |
| 1003 | if (result) | 1030 | if (result) |
| 1004 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1031 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
| 1005 | result = sysfs_create_link(&device->cdev->device.kobj, | 1032 | result = sysfs_create_link(&device->cooling_dev->device.kobj, |
| 1006 | &device->dev->dev.kobj, "device"); | 1033 | &device->dev->dev.kobj, "device"); |
| 1007 | if (result) | 1034 | if (result) |
| 1008 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1035 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
| @@ -1039,7 +1066,6 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
| 1039 | { | 1066 | { |
| 1040 | acpi_handle h_dummy1; | 1067 | acpi_handle h_dummy1; |
| 1041 | 1068 | ||
| 1042 | memset(&video->cap, 0, sizeof(video->cap)); | ||
| 1043 | if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { | 1069 | if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { |
| 1044 | video->cap._DOS = 1; | 1070 | video->cap._DOS = 1; |
| 1045 | } | 1071 | } |
| @@ -2009,13 +2035,13 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
| 2009 | backlight_device_unregister(device->backlight); | 2035 | backlight_device_unregister(device->backlight); |
| 2010 | device->backlight = NULL; | 2036 | device->backlight = NULL; |
| 2011 | } | 2037 | } |
| 2012 | if (device->cdev) { | 2038 | if (device->cooling_dev) { |
| 2013 | sysfs_remove_link(&device->dev->dev.kobj, | 2039 | sysfs_remove_link(&device->dev->dev.kobj, |
| 2014 | "thermal_cooling"); | 2040 | "thermal_cooling"); |
| 2015 | sysfs_remove_link(&device->cdev->device.kobj, | 2041 | sysfs_remove_link(&device->cooling_dev->device.kobj, |
| 2016 | "device"); | 2042 | "device"); |
| 2017 | thermal_cooling_device_unregister(device->cdev); | 2043 | thermal_cooling_device_unregister(device->cooling_dev); |
| 2018 | device->cdev = NULL; | 2044 | device->cooling_dev = NULL; |
| 2019 | } | 2045 | } |
| 2020 | video_output_unregister(device->output_dev); | 2046 | video_output_unregister(device->output_dev); |
| 2021 | 2047 | ||
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 7cd2b63435ea..7032f25da9b5 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | 40 | ||
| 41 | #define PREFIX "ACPI: " | ||
| 42 | |||
| 41 | ACPI_MODULE_NAME("video"); | 43 | ACPI_MODULE_NAME("video"); |
| 42 | #define _COMPONENT ACPI_VIDEO_COMPONENT | 44 | #define _COMPONENT ACPI_VIDEO_COMPONENT |
| 43 | 45 | ||
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 501e293e5ad0..9047b2714653 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
| @@ -476,7 +476,6 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) | |||
| 476 | { | 476 | { |
| 477 | acpi_handle handle, parent; | 477 | acpi_handle handle, parent; |
| 478 | acpi_status status; | 478 | acpi_status status; |
| 479 | struct acpi_buffer buffer; | ||
| 480 | struct acpi_device_info *info; | 479 | struct acpi_device_info *info; |
| 481 | u64 lba_hpa, sba_hpa, length; | 480 | u64 lba_hpa, sba_hpa, length; |
| 482 | int match; | 481 | int match; |
| @@ -488,13 +487,11 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) | |||
| 488 | /* Look for an enclosing IOC scope and find its CSR space */ | 487 | /* Look for an enclosing IOC scope and find its CSR space */ |
| 489 | handle = obj; | 488 | handle = obj; |
| 490 | do { | 489 | do { |
| 491 | buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | 490 | status = acpi_get_object_info(handle, &info); |
| 492 | status = acpi_get_object_info(handle, &buffer); | ||
| 493 | if (ACPI_SUCCESS(status)) { | 491 | if (ACPI_SUCCESS(status)) { |
| 494 | /* TBD check _CID also */ | 492 | /* TBD check _CID also */ |
| 495 | info = buffer.pointer; | 493 | info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0'; |
| 496 | info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; | 494 | match = (strcmp(info->hardware_id.string, "HWP0001") == 0); |
| 497 | match = (strcmp(info->hardware_id.value, "HWP0001") == 0); | ||
| 498 | kfree(info); | 495 | kfree(info); |
| 499 | if (match) { | 496 | if (match) { |
| 500 | status = hp_acpi_csr_space(handle, &sba_hpa, &length); | 497 | status = hp_acpi_csr_space(handle, &sba_hpa, &length); |
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index c509c9916464..c0cf45a11b93 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
| @@ -114,8 +114,6 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, | |||
| 114 | unsigned int bus, devnum, func; | 114 | unsigned int bus, devnum, func; |
| 115 | acpi_integer addr; | 115 | acpi_integer addr; |
| 116 | acpi_handle dev_handle; | 116 | acpi_handle dev_handle; |
| 117 | struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, | ||
| 118 | .pointer = NULL}; | ||
| 119 | acpi_status status; | 117 | acpi_status status; |
| 120 | struct acpi_device_info *dinfo = NULL; | 118 | struct acpi_device_info *dinfo = NULL; |
| 121 | int ret = -ENODEV; | 119 | int ret = -ENODEV; |
| @@ -134,12 +132,11 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, | |||
| 134 | goto err; | 132 | goto err; |
| 135 | } | 133 | } |
| 136 | 134 | ||
| 137 | status = acpi_get_object_info(dev_handle, &buffer); | 135 | status = acpi_get_object_info(dev_handle, &dinfo); |
| 138 | if (ACPI_FAILURE(status)) { | 136 | if (ACPI_FAILURE(status)) { |
| 139 | DEBPRINT("get_object_info for device failed\n"); | 137 | DEBPRINT("get_object_info for device failed\n"); |
| 140 | goto err; | 138 | goto err; |
| 141 | } | 139 | } |
| 142 | dinfo = buffer.pointer; | ||
| 143 | if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && | 140 | if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && |
| 144 | dinfo->address == addr) { | 141 | dinfo->address == addr) { |
| 145 | *pcidevfn = addr; | 142 | *pcidevfn = addr; |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index ab99783dccec..5f6b915d0d82 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
| @@ -34,9 +34,9 @@ | |||
| 34 | #include <linux/irq.h> | 34 | #include <linux/irq.h> |
| 35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
| 36 | #include <linux/tboot.h> | 36 | #include <linux/tboot.h> |
| 37 | #include <linux/dmi.h> | ||
| 37 | 38 | ||
| 38 | #undef PREFIX | 39 | #define PREFIX "DMAR: " |
| 39 | #define PREFIX "DMAR:" | ||
| 40 | 40 | ||
| 41 | /* No locks are needed as DMA remapping hardware unit | 41 | /* No locks are needed as DMA remapping hardware unit |
| 42 | * list is constructed at boot time and hotplug of | 42 | * list is constructed at boot time and hotplug of |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 5befa7e379b7..a9d926b7d805 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
| @@ -398,23 +398,21 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, | |||
| 398 | acpi_handle *phandle = (acpi_handle *)context; | 398 | acpi_handle *phandle = (acpi_handle *)context; |
| 399 | acpi_status status; | 399 | acpi_status status; |
| 400 | struct acpi_device_info *info; | 400 | struct acpi_device_info *info; |
| 401 | struct acpi_buffer info_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 402 | int retval = 0; | 401 | int retval = 0; |
| 403 | 402 | ||
| 404 | status = acpi_get_object_info(handle, &info_buffer); | 403 | status = acpi_get_object_info(handle, &info); |
| 405 | if (ACPI_FAILURE(status)) { | 404 | if (ACPI_FAILURE(status)) { |
| 406 | err("%s: Failed to get device information status=0x%x\n", | 405 | err("%s: Failed to get device information status=0x%x\n", |
| 407 | __func__, status); | 406 | __func__, status); |
| 408 | return retval; | 407 | return retval; |
| 409 | } | 408 | } |
| 410 | info = info_buffer.pointer; | 409 | info->hardware_id.string[sizeof(info->hardware_id.length) - 1] = '\0'; |
| 411 | info->hardware_id.value[sizeof(info->hardware_id.value) - 1] = '\0'; | ||
| 412 | 410 | ||
| 413 | if (info->current_status && (info->valid & ACPI_VALID_HID) && | 411 | if (info->current_status && (info->valid & ACPI_VALID_HID) && |
| 414 | (!strcmp(info->hardware_id.value, IBM_HARDWARE_ID1) || | 412 | (!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) || |
| 415 | !strcmp(info->hardware_id.value, IBM_HARDWARE_ID2))) { | 413 | !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) { |
| 416 | dbg("found hardware: %s, handle: %p\n", | 414 | dbg("found hardware: %s, handle: %p\n", |
| 417 | info->hardware_id.value, handle); | 415 | info->hardware_id.string, handle); |
| 418 | *phandle = handle; | 416 | *phandle = handle; |
| 419 | /* returning non-zero causes the search to stop | 417 | /* returning non-zero causes the search to stop |
| 420 | * and returns this value to the caller of | 418 | * and returns this value to the caller of |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 77c6097ced80..55ca39dea42e 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -99,6 +99,7 @@ config FUJITSU_LAPTOP | |||
| 99 | depends on ACPI | 99 | depends on ACPI |
| 100 | depends on INPUT | 100 | depends on INPUT |
| 101 | depends on BACKLIGHT_CLASS_DEVICE | 101 | depends on BACKLIGHT_CLASS_DEVICE |
| 102 | depends on LEDS_CLASS || LEDS_CLASS=n | ||
| 102 | ---help--- | 103 | ---help--- |
| 103 | This is a driver for laptops built by Fujitsu: | 104 | This is a driver for laptops built by Fujitsu: |
| 104 | 105 | ||
| @@ -396,6 +397,15 @@ config ACPI_ASUS | |||
| 396 | NOTE: This driver is deprecated and will probably be removed soon, | 397 | NOTE: This driver is deprecated and will probably be removed soon, |
| 397 | use asus-laptop instead. | 398 | use asus-laptop instead. |
| 398 | 399 | ||
| 400 | config TOPSTAR_LAPTOP | ||
| 401 | tristate "Topstar Laptop Extras" | ||
| 402 | depends on ACPI | ||
| 403 | depends on INPUT | ||
| 404 | ---help--- | ||
| 405 | This driver adds support for hotkeys found on Topstar laptops. | ||
| 406 | |||
| 407 | If you have a Topstar laptop, say Y or M here. | ||
| 408 | |||
| 399 | config ACPI_TOSHIBA | 409 | config ACPI_TOSHIBA |
| 400 | tristate "Toshiba Laptop Extras" | 410 | tristate "Toshiba Laptop Extras" |
| 401 | depends on ACPI | 411 | depends on ACPI |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 641b8bfa5538..d1c16210a512 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -19,4 +19,5 @@ obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o | |||
| 19 | obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o | 19 | obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o |
| 20 | obj-$(CONFIG_ACPI_WMI) += wmi.o | 20 | obj-$(CONFIG_ACPI_WMI) += wmi.o |
| 21 | obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o | 21 | obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o |
| 22 | obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o | ||
| 22 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o | 23 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o |
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index bdfee177eefb..0a8f735f6c4a 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | */ | 52 | */ |
| 53 | #undef START_IN_KERNEL_MODE | 53 | #undef START_IN_KERNEL_MODE |
| 54 | 54 | ||
| 55 | #define DRV_VER "0.5.13" | 55 | #define DRV_VER "0.5.17" |
| 56 | 56 | ||
| 57 | /* | 57 | /* |
| 58 | * According to the Atom N270 datasheet, | 58 | * According to the Atom N270 datasheet, |
| @@ -90,6 +90,7 @@ static unsigned int fanoff = 58; | |||
| 90 | static unsigned int verbose; | 90 | static unsigned int verbose; |
| 91 | static unsigned int fanstate = ACERHDF_FAN_AUTO; | 91 | static unsigned int fanstate = ACERHDF_FAN_AUTO; |
| 92 | static char force_bios[16]; | 92 | static char force_bios[16]; |
| 93 | static char force_product[16]; | ||
| 93 | static unsigned int prev_interval; | 94 | static unsigned int prev_interval; |
| 94 | struct thermal_zone_device *thz_dev; | 95 | struct thermal_zone_device *thz_dev; |
| 95 | struct thermal_cooling_device *cl_dev; | 96 | struct thermal_cooling_device *cl_dev; |
| @@ -107,34 +108,62 @@ module_param(verbose, uint, 0600); | |||
| 107 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); | 108 | MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); |
| 108 | module_param_string(force_bios, force_bios, 16, 0); | 109 | module_param_string(force_bios, force_bios, 16, 0); |
| 109 | MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); | 110 | MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); |
| 111 | module_param_string(force_product, force_product, 16, 0); | ||
| 112 | MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); | ||
| 113 | |||
| 114 | /* | ||
| 115 | * cmd_off: to switch the fan completely off / to check if the fan is off | ||
| 116 | * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then | ||
| 117 | * the fan speed depending on the temperature | ||
| 118 | */ | ||
| 119 | struct fancmd { | ||
| 120 | u8 cmd_off; | ||
| 121 | u8 cmd_auto; | ||
| 122 | }; | ||
| 110 | 123 | ||
| 111 | /* BIOS settings */ | 124 | /* BIOS settings */ |
| 112 | struct bios_settings_t { | 125 | struct bios_settings_t { |
| 113 | const char *vendor; | 126 | const char *vendor; |
| 127 | const char *product; | ||
| 114 | const char *version; | 128 | const char *version; |
| 115 | unsigned char fanreg; | 129 | unsigned char fanreg; |
| 116 | unsigned char tempreg; | 130 | unsigned char tempreg; |
| 117 | unsigned char fancmd[2]; /* fan off and auto commands */ | 131 | struct fancmd cmd; |
| 118 | }; | 132 | }; |
| 119 | 133 | ||
| 120 | /* Register addresses and values for different BIOS versions */ | 134 | /* Register addresses and values for different BIOS versions */ |
| 121 | static const struct bios_settings_t bios_tbl[] = { | 135 | static const struct bios_settings_t bios_tbl[] = { |
| 122 | {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, | 136 | /* AOA110 */ |
| 123 | {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, | 137 | {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, |
| 124 | {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, | 138 | {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, |
| 125 | {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, | 139 | {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, |
| 126 | {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, | 140 | {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, |
| 127 | {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, | 141 | {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, |
| 128 | {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, | 142 | {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, |
| 129 | {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, | 143 | {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, |
| 130 | {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, | 144 | {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, |
| 131 | {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, | 145 | {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, |
| 132 | {"", "", 0, 0, {0, 0} } | 146 | /* AOA150 */ |
| 147 | {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} }, | ||
| 148 | {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, | ||
| 149 | {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, | ||
| 150 | {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, | ||
| 151 | {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, | ||
| 152 | {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, | ||
| 153 | {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, | ||
| 154 | {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, | ||
| 155 | /* special BIOS / other */ | ||
| 156 | {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, | ||
| 157 | {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, | ||
| 158 | {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, | ||
| 159 | {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, | ||
| 160 | {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, | ||
| 161 | /* pewpew-terminator */ | ||
| 162 | {"", "", "", 0, 0, {0, 0} } | ||
| 133 | }; | 163 | }; |
| 134 | 164 | ||
| 135 | static const struct bios_settings_t *bios_cfg __read_mostly; | 165 | static const struct bios_settings_t *bios_cfg __read_mostly; |
| 136 | 166 | ||
| 137 | |||
| 138 | static int acerhdf_get_temp(int *temp) | 167 | static int acerhdf_get_temp(int *temp) |
| 139 | { | 168 | { |
| 140 | u8 read_temp; | 169 | u8 read_temp; |
| @@ -150,13 +179,14 @@ static int acerhdf_get_temp(int *temp) | |||
| 150 | static int acerhdf_get_fanstate(int *state) | 179 | static int acerhdf_get_fanstate(int *state) |
| 151 | { | 180 | { |
| 152 | u8 fan; | 181 | u8 fan; |
| 153 | bool tmp; | ||
| 154 | 182 | ||
| 155 | if (ec_read(bios_cfg->fanreg, &fan)) | 183 | if (ec_read(bios_cfg->fanreg, &fan)) |
| 156 | return -EINVAL; | 184 | return -EINVAL; |
| 157 | 185 | ||
| 158 | tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]); | 186 | if (fan != bios_cfg->cmd.cmd_off) |
| 159 | *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO; | 187 | *state = ACERHDF_FAN_AUTO; |
| 188 | else | ||
| 189 | *state = ACERHDF_FAN_OFF; | ||
| 160 | 190 | ||
| 161 | return 0; | 191 | return 0; |
| 162 | } | 192 | } |
| @@ -175,7 +205,8 @@ static void acerhdf_change_fanstate(int state) | |||
| 175 | state = ACERHDF_FAN_AUTO; | 205 | state = ACERHDF_FAN_AUTO; |
| 176 | } | 206 | } |
| 177 | 207 | ||
| 178 | cmd = bios_cfg->fancmd[state]; | 208 | cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off |
| 209 | : bios_cfg->cmd.cmd_auto; | ||
| 179 | fanstate = state; | 210 | fanstate = state; |
| 180 | 211 | ||
| 181 | ec_write(bios_cfg->fanreg, cmd); | 212 | ec_write(bios_cfg->fanreg, cmd); |
| @@ -408,7 +439,7 @@ struct thermal_cooling_device_ops acerhdf_cooling_ops = { | |||
| 408 | }; | 439 | }; |
| 409 | 440 | ||
| 410 | /* suspend / resume functionality */ | 441 | /* suspend / resume functionality */ |
| 411 | static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) | 442 | static int acerhdf_suspend(struct device *dev) |
| 412 | { | 443 | { |
| 413 | if (kernelmode) | 444 | if (kernelmode) |
| 414 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); | 445 | acerhdf_change_fanstate(ACERHDF_FAN_AUTO); |
| @@ -419,14 +450,6 @@ static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) | |||
| 419 | return 0; | 450 | return 0; |
| 420 | } | 451 | } |
| 421 | 452 | ||
| 422 | static int acerhdf_resume(struct platform_device *device) | ||
| 423 | { | ||
| 424 | if (verbose) | ||
| 425 | pr_notice("resuming\n"); | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int __devinit acerhdf_probe(struct platform_device *device) | 453 | static int __devinit acerhdf_probe(struct platform_device *device) |
| 431 | { | 454 | { |
| 432 | return 0; | 455 | return 0; |
| @@ -437,15 +460,19 @@ static int acerhdf_remove(struct platform_device *device) | |||
| 437 | return 0; | 460 | return 0; |
| 438 | } | 461 | } |
| 439 | 462 | ||
| 440 | struct platform_driver acerhdf_drv = { | 463 | static struct dev_pm_ops acerhdf_pm_ops = { |
| 464 | .suspend = acerhdf_suspend, | ||
| 465 | .freeze = acerhdf_suspend, | ||
| 466 | }; | ||
| 467 | |||
| 468 | static struct platform_driver acerhdf_driver = { | ||
| 441 | .driver = { | 469 | .driver = { |
| 442 | .name = "acerhdf", | 470 | .name = "acerhdf", |
| 443 | .owner = THIS_MODULE, | 471 | .owner = THIS_MODULE, |
| 472 | .pm = &acerhdf_pm_ops, | ||
| 444 | }, | 473 | }, |
| 445 | .probe = acerhdf_probe, | 474 | .probe = acerhdf_probe, |
| 446 | .remove = acerhdf_remove, | 475 | .remove = acerhdf_remove, |
| 447 | .suspend = acerhdf_suspend, | ||
| 448 | .resume = acerhdf_resume, | ||
| 449 | }; | 476 | }; |
| 450 | 477 | ||
| 451 | 478 | ||
| @@ -454,32 +481,40 @@ static int acerhdf_check_hardware(void) | |||
| 454 | { | 481 | { |
| 455 | char const *vendor, *version, *product; | 482 | char const *vendor, *version, *product; |
| 456 | int i; | 483 | int i; |
| 484 | unsigned long prod_len = 0; | ||
| 457 | 485 | ||
| 458 | /* get BIOS data */ | 486 | /* get BIOS data */ |
| 459 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); | 487 | vendor = dmi_get_system_info(DMI_SYS_VENDOR); |
| 460 | version = dmi_get_system_info(DMI_BIOS_VERSION); | 488 | version = dmi_get_system_info(DMI_BIOS_VERSION); |
| 461 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 489 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
| 462 | 490 | ||
| 491 | |||
| 463 | pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); | 492 | pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); |
| 464 | 493 | ||
| 465 | if (!force_bios[0]) { | 494 | if (force_bios[0]) { |
| 466 | if (strncmp(product, "AO", 2)) { | ||
| 467 | pr_err("no Aspire One hardware found\n"); | ||
| 468 | return -EINVAL; | ||
| 469 | } | ||
| 470 | } else { | ||
| 471 | pr_info("forcing BIOS version: %s\n", version); | ||
| 472 | version = force_bios; | 495 | version = force_bios; |
| 496 | pr_info("forcing BIOS version: %s\n", version); | ||
| 497 | kernelmode = 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | if (force_product[0]) { | ||
| 501 | product = force_product; | ||
| 502 | pr_info("forcing BIOS product: %s\n", product); | ||
| 473 | kernelmode = 0; | 503 | kernelmode = 0; |
| 474 | } | 504 | } |
| 475 | 505 | ||
| 506 | prod_len = strlen(product); | ||
| 507 | |||
| 476 | if (verbose) | 508 | if (verbose) |
| 477 | pr_info("BIOS info: %s %s, product: %s\n", | 509 | pr_info("BIOS info: %s %s, product: %s\n", |
| 478 | vendor, version, product); | 510 | vendor, version, product); |
| 479 | 511 | ||
| 480 | /* search BIOS version and vendor in BIOS settings table */ | 512 | /* search BIOS version and vendor in BIOS settings table */ |
| 481 | for (i = 0; bios_tbl[i].version[0]; i++) { | 513 | for (i = 0; bios_tbl[i].version[0]; i++) { |
| 482 | if (!strcmp(bios_tbl[i].vendor, vendor) && | 514 | if (strlen(bios_tbl[i].product) >= prod_len && |
| 515 | !strncmp(bios_tbl[i].product, product, | ||
| 516 | strlen(bios_tbl[i].product)) && | ||
| 517 | !strcmp(bios_tbl[i].vendor, vendor) && | ||
| 483 | !strcmp(bios_tbl[i].version, version)) { | 518 | !strcmp(bios_tbl[i].version, version)) { |
| 484 | bios_cfg = &bios_tbl[i]; | 519 | bios_cfg = &bios_tbl[i]; |
| 485 | break; | 520 | break; |
| @@ -487,8 +522,8 @@ static int acerhdf_check_hardware(void) | |||
| 487 | } | 522 | } |
| 488 | 523 | ||
| 489 | if (!bios_cfg) { | 524 | if (!bios_cfg) { |
| 490 | pr_err("unknown (unsupported) BIOS version %s/%s, " | 525 | pr_err("unknown (unsupported) BIOS version %s/%s/%s, " |
| 491 | "please report, aborting!\n", vendor, version); | 526 | "please report, aborting!\n", vendor, product, version); |
| 492 | return -EINVAL; | 527 | return -EINVAL; |
| 493 | } | 528 | } |
| 494 | 529 | ||
| @@ -509,7 +544,7 @@ static int acerhdf_register_platform(void) | |||
| 509 | { | 544 | { |
| 510 | int err = 0; | 545 | int err = 0; |
| 511 | 546 | ||
| 512 | err = platform_driver_register(&acerhdf_drv); | 547 | err = platform_driver_register(&acerhdf_driver); |
| 513 | if (err) | 548 | if (err) |
| 514 | return err; | 549 | return err; |
| 515 | 550 | ||
| @@ -525,7 +560,7 @@ static void acerhdf_unregister_platform(void) | |||
| 525 | return; | 560 | return; |
| 526 | 561 | ||
| 527 | platform_device_del(acerhdf_dev); | 562 | platform_device_del(acerhdf_dev); |
| 528 | platform_driver_unregister(&acerhdf_drv); | 563 | platform_driver_unregister(&acerhdf_driver); |
| 529 | } | 564 | } |
| 530 | 565 | ||
| 531 | static int acerhdf_register_thermal(void) | 566 | static int acerhdf_register_thermal(void) |
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index db657bbeec90..b39d2bb3e75b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
| @@ -77,15 +77,16 @@ | |||
| 77 | * Flags for hotk status | 77 | * Flags for hotk status |
| 78 | * WL_ON and BT_ON are also used for wireless_status() | 78 | * WL_ON and BT_ON are also used for wireless_status() |
| 79 | */ | 79 | */ |
| 80 | #define WL_ON 0x01 //internal Wifi | 80 | #define WL_ON 0x01 /* internal Wifi */ |
| 81 | #define BT_ON 0x02 //internal Bluetooth | 81 | #define BT_ON 0x02 /* internal Bluetooth */ |
| 82 | #define MLED_ON 0x04 //mail LED | 82 | #define MLED_ON 0x04 /* mail LED */ |
| 83 | #define TLED_ON 0x08 //touchpad LED | 83 | #define TLED_ON 0x08 /* touchpad LED */ |
| 84 | #define RLED_ON 0x10 //Record LED | 84 | #define RLED_ON 0x10 /* Record LED */ |
| 85 | #define PLED_ON 0x20 //Phone LED | 85 | #define PLED_ON 0x20 /* Phone LED */ |
| 86 | #define GLED_ON 0x40 //Gaming LED | 86 | #define GLED_ON 0x40 /* Gaming LED */ |
| 87 | #define LCD_ON 0x80 //LCD backlight | 87 | #define LCD_ON 0x80 /* LCD backlight */ |
| 88 | #define GPS_ON 0x100 //GPS | 88 | #define GPS_ON 0x100 /* GPS */ |
| 89 | #define KEY_ON 0x200 /* Keyboard backlight */ | ||
| 89 | 90 | ||
| 90 | #define ASUS_LOG ASUS_HOTK_FILE ": " | 91 | #define ASUS_LOG ASUS_HOTK_FILE ": " |
| 91 | #define ASUS_ERR KERN_ERR ASUS_LOG | 92 | #define ASUS_ERR KERN_ERR ASUS_LOG |
| @@ -98,7 +99,8 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); | |||
| 98 | MODULE_DESCRIPTION(ASUS_HOTK_NAME); | 99 | MODULE_DESCRIPTION(ASUS_HOTK_NAME); |
| 99 | MODULE_LICENSE("GPL"); | 100 | MODULE_LICENSE("GPL"); |
| 100 | 101 | ||
| 101 | /* WAPF defines the behavior of the Fn+Fx wlan key | 102 | /* |
| 103 | * WAPF defines the behavior of the Fn+Fx wlan key | ||
| 102 | * The significance of values is yet to be found, but | 104 | * The significance of values is yet to be found, but |
| 103 | * most of the time: | 105 | * most of the time: |
| 104 | * 0x0 will do nothing | 106 | * 0x0 will do nothing |
| @@ -125,7 +127,8 @@ ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */ | |||
| 125 | /* LEDD */ | 127 | /* LEDD */ |
| 126 | ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); | 128 | ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); |
| 127 | 129 | ||
| 128 | /* Bluetooth and WLAN | 130 | /* |
| 131 | * Bluetooth and WLAN | ||
| 129 | * WLED and BLED are not handled like other XLED, because in some dsdt | 132 | * WLED and BLED are not handled like other XLED, because in some dsdt |
| 130 | * they also control the WLAN/Bluetooth device. | 133 | * they also control the WLAN/Bluetooth device. |
| 131 | */ | 134 | */ |
| @@ -149,22 +152,32 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ | |||
| 149 | 152 | ||
| 150 | /* Display */ | 153 | /* Display */ |
| 151 | ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); | 154 | ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); |
| 152 | ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G | 155 | ASUS_HANDLE(display_get, |
| 153 | M6A M6V VX-1 V6J V6V W3Z */ | 156 | /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ |
| 154 | "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V | 157 | "\\_SB.PCI0.P0P1.VGA.GETD", |
| 155 | S5A M5A z33A W1Jc W2V G1 */ | 158 | /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ |
| 156 | "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ | 159 | "\\_SB.PCI0.P0P2.VGA.GETD", |
| 157 | "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ | 160 | /* A6V A6Q */ |
| 158 | "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ | 161 | "\\_SB.PCI0.P0P3.VGA.GETD", |
| 159 | "\\_SB.PCI0.VGA.GETD", /* Z96F */ | 162 | /* A6T, A6M */ |
| 160 | "\\ACTD", /* A2D */ | 163 | "\\_SB.PCI0.P0PA.VGA.GETD", |
| 161 | "\\ADVG", /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ | 164 | /* L3C */ |
| 162 | "\\DNXT", /* P30 */ | 165 | "\\_SB.PCI0.PCI1.VGAC.NMAP", |
| 163 | "\\INFB", /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ | 166 | /* Z96F */ |
| 164 | "\\SSTE"); /* A3F A6F A3N A3L M6N W3N W6A */ | 167 | "\\_SB.PCI0.VGA.GETD", |
| 165 | 168 | /* A2D */ | |
| 166 | ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ | 169 | "\\ACTD", |
| 167 | ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ | 170 | /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ |
| 171 | "\\ADVG", | ||
| 172 | /* P30 */ | ||
| 173 | "\\DNXT", | ||
| 174 | /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ | ||
| 175 | "\\INFB", | ||
| 176 | /* A3F A6F A3N A3L M6N W3N W6A */ | ||
| 177 | "\\SSTE"); | ||
| 178 | |||
| 179 | ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ | ||
| 180 | ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ | ||
| 168 | 181 | ||
| 169 | /* GPS */ | 182 | /* GPS */ |
| 170 | /* R2H use different handle for GPS on/off */ | 183 | /* R2H use different handle for GPS on/off */ |
| @@ -172,19 +185,23 @@ ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ | |||
| 172 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ | 185 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ |
| 173 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); | 186 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); |
| 174 | 187 | ||
| 188 | /* Keyboard light */ | ||
| 189 | ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB"); | ||
| 190 | ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); | ||
| 191 | |||
| 175 | /* | 192 | /* |
| 176 | * This is the main structure, we can use it to store anything interesting | 193 | * This is the main structure, we can use it to store anything interesting |
| 177 | * about the hotk device | 194 | * about the hotk device |
| 178 | */ | 195 | */ |
| 179 | struct asus_hotk { | 196 | struct asus_hotk { |
| 180 | char *name; //laptop name | 197 | char *name; /* laptop name */ |
| 181 | struct acpi_device *device; //the device we are in | 198 | struct acpi_device *device; /* the device we are in */ |
| 182 | acpi_handle handle; //the handle of the hotk device | 199 | acpi_handle handle; /* the handle of the hotk device */ |
| 183 | char status; //status of the hotk, for LEDs, ... | 200 | char status; /* status of the hotk, for LEDs, ... */ |
| 184 | u32 ledd_status; //status of the LED display | 201 | u32 ledd_status; /* status of the LED display */ |
| 185 | u8 light_level; //light sensor level | 202 | u8 light_level; /* light sensor level */ |
| 186 | u8 light_switch; //light sensor switch value | 203 | u8 light_switch; /* light sensor switch value */ |
| 187 | u16 event_count[128]; //count for each event TODO make this better | 204 | u16 event_count[128]; /* count for each event TODO make this better */ |
| 188 | struct input_dev *inputdev; | 205 | struct input_dev *inputdev; |
| 189 | u16 *keycode_map; | 206 | u16 *keycode_map; |
| 190 | }; | 207 | }; |
| @@ -237,28 +254,35 @@ static struct backlight_ops asusbl_ops = { | |||
| 237 | .update_status = update_bl_status, | 254 | .update_status = update_bl_status, |
| 238 | }; | 255 | }; |
| 239 | 256 | ||
| 240 | /* These functions actually update the LED's, and are called from a | 257 | /* |
| 258 | * These functions actually update the LED's, and are called from a | ||
| 241 | * workqueue. By doing this as separate work rather than when the LED | 259 | * workqueue. By doing this as separate work rather than when the LED |
| 242 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a | 260 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a |
| 243 | * potentially bad time, such as a timer interrupt. */ | 261 | * potentially bad time, such as a timer interrupt. |
| 262 | */ | ||
| 244 | static struct workqueue_struct *led_workqueue; | 263 | static struct workqueue_struct *led_workqueue; |
| 245 | 264 | ||
| 246 | #define ASUS_LED(object, ledname) \ | 265 | #define ASUS_LED(object, ledname, max) \ |
| 247 | static void object##_led_set(struct led_classdev *led_cdev, \ | 266 | static void object##_led_set(struct led_classdev *led_cdev, \ |
| 248 | enum led_brightness value); \ | 267 | enum led_brightness value); \ |
| 268 | static enum led_brightness object##_led_get( \ | ||
| 269 | struct led_classdev *led_cdev); \ | ||
| 249 | static void object##_led_update(struct work_struct *ignored); \ | 270 | static void object##_led_update(struct work_struct *ignored); \ |
| 250 | static int object##_led_wk; \ | 271 | static int object##_led_wk; \ |
| 251 | static DECLARE_WORK(object##_led_work, object##_led_update); \ | 272 | static DECLARE_WORK(object##_led_work, object##_led_update); \ |
| 252 | static struct led_classdev object##_led = { \ | 273 | static struct led_classdev object##_led = { \ |
| 253 | .name = "asus::" ledname, \ | 274 | .name = "asus::" ledname, \ |
| 254 | .brightness_set = object##_led_set, \ | 275 | .brightness_set = object##_led_set, \ |
| 276 | .brightness_get = object##_led_get, \ | ||
| 277 | .max_brightness = max \ | ||
| 255 | } | 278 | } |
| 256 | 279 | ||
| 257 | ASUS_LED(mled, "mail"); | 280 | ASUS_LED(mled, "mail", 1); |
| 258 | ASUS_LED(tled, "touchpad"); | 281 | ASUS_LED(tled, "touchpad", 1); |
| 259 | ASUS_LED(rled, "record"); | 282 | ASUS_LED(rled, "record", 1); |
| 260 | ASUS_LED(pled, "phone"); | 283 | ASUS_LED(pled, "phone", 1); |
| 261 | ASUS_LED(gled, "gaming"); | 284 | ASUS_LED(gled, "gaming", 1); |
| 285 | ASUS_LED(kled, "kbd_backlight", 3); | ||
| 262 | 286 | ||
| 263 | struct key_entry { | 287 | struct key_entry { |
| 264 | char type; | 288 | char type; |
| @@ -278,16 +302,23 @@ static struct key_entry asus_keymap[] = { | |||
| 278 | {KE_KEY, 0x41, KEY_NEXTSONG}, | 302 | {KE_KEY, 0x41, KEY_NEXTSONG}, |
| 279 | {KE_KEY, 0x43, KEY_STOPCD}, | 303 | {KE_KEY, 0x43, KEY_STOPCD}, |
| 280 | {KE_KEY, 0x45, KEY_PLAYPAUSE}, | 304 | {KE_KEY, 0x45, KEY_PLAYPAUSE}, |
| 305 | {KE_KEY, 0x4c, KEY_MEDIA}, | ||
| 281 | {KE_KEY, 0x50, KEY_EMAIL}, | 306 | {KE_KEY, 0x50, KEY_EMAIL}, |
| 282 | {KE_KEY, 0x51, KEY_WWW}, | 307 | {KE_KEY, 0x51, KEY_WWW}, |
| 308 | {KE_KEY, 0x55, KEY_CALC}, | ||
| 283 | {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ | 309 | {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ |
| 284 | {KE_KEY, 0x5D, KEY_WLAN}, | 310 | {KE_KEY, 0x5D, KEY_WLAN}, |
| 311 | {KE_KEY, 0x5E, KEY_WLAN}, | ||
| 312 | {KE_KEY, 0x5F, KEY_WLAN}, | ||
| 313 | {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, | ||
| 285 | {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, | 314 | {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, |
| 286 | {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ | 315 | {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ |
| 287 | {KE_KEY, 0x82, KEY_CAMERA}, | 316 | {KE_KEY, 0x82, KEY_CAMERA}, |
| 288 | {KE_KEY, 0x8A, KEY_PROG1}, | 317 | {KE_KEY, 0x8A, KEY_PROG1}, |
| 289 | {KE_KEY, 0x95, KEY_MEDIA}, | 318 | {KE_KEY, 0x95, KEY_MEDIA}, |
| 290 | {KE_KEY, 0x99, KEY_PHONE}, | 319 | {KE_KEY, 0x99, KEY_PHONE}, |
| 320 | {KE_KEY, 0xc4, KEY_KBDILLUMUP}, | ||
| 321 | {KE_KEY, 0xc5, KEY_KBDILLUMDOWN}, | ||
| 291 | {KE_END, 0}, | 322 | {KE_END, 0}, |
| 292 | }; | 323 | }; |
| 293 | 324 | ||
| @@ -301,8 +332,8 @@ static struct key_entry asus_keymap[] = { | |||
| 301 | static int write_acpi_int(acpi_handle handle, const char *method, int val, | 332 | static int write_acpi_int(acpi_handle handle, const char *method, int val, |
| 302 | struct acpi_buffer *output) | 333 | struct acpi_buffer *output) |
| 303 | { | 334 | { |
| 304 | struct acpi_object_list params; //list of input parameters (an int here) | 335 | struct acpi_object_list params; /* list of input parameters (an int) */ |
| 305 | union acpi_object in_obj; //the only param we use | 336 | union acpi_object in_obj; /* the only param we use */ |
| 306 | acpi_status status; | 337 | acpi_status status; |
| 307 | 338 | ||
| 308 | if (!handle) | 339 | if (!handle) |
| @@ -399,6 +430,11 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
| 399 | { \ | 430 | { \ |
| 400 | int value = object##_led_wk; \ | 431 | int value = object##_led_wk; \ |
| 401 | write_status(object##_set_handle, value, (mask)); \ | 432 | write_status(object##_set_handle, value, (mask)); \ |
| 433 | } \ | ||
| 434 | static enum led_brightness object##_led_get( \ | ||
| 435 | struct led_classdev *led_cdev) \ | ||
| 436 | { \ | ||
| 437 | return led_cdev->brightness; \ | ||
| 402 | } | 438 | } |
| 403 | 439 | ||
| 404 | ASUS_LED_HANDLER(mled, MLED_ON); | 440 | ASUS_LED_HANDLER(mled, MLED_ON); |
| @@ -407,6 +443,60 @@ ASUS_LED_HANDLER(rled, RLED_ON); | |||
| 407 | ASUS_LED_HANDLER(tled, TLED_ON); | 443 | ASUS_LED_HANDLER(tled, TLED_ON); |
| 408 | ASUS_LED_HANDLER(gled, GLED_ON); | 444 | ASUS_LED_HANDLER(gled, GLED_ON); |
| 409 | 445 | ||
| 446 | /* | ||
| 447 | * Keyboard backlight | ||
| 448 | */ | ||
| 449 | static int get_kled_lvl(void) | ||
| 450 | { | ||
| 451 | unsigned long long kblv; | ||
| 452 | struct acpi_object_list params; | ||
| 453 | union acpi_object in_obj; | ||
| 454 | acpi_status rv; | ||
| 455 | |||
| 456 | params.count = 1; | ||
| 457 | params.pointer = &in_obj; | ||
| 458 | in_obj.type = ACPI_TYPE_INTEGER; | ||
| 459 | in_obj.integer.value = 2; | ||
| 460 | |||
| 461 | rv = acpi_evaluate_integer(kled_get_handle, NULL, ¶ms, &kblv); | ||
| 462 | if (ACPI_FAILURE(rv)) { | ||
| 463 | pr_warning("Error reading kled level\n"); | ||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | return kblv; | ||
| 467 | } | ||
| 468 | |||
| 469 | static int set_kled_lvl(int kblv) | ||
| 470 | { | ||
| 471 | if (kblv > 0) | ||
| 472 | kblv = (1 << 7) | (kblv & 0x7F); | ||
| 473 | else | ||
| 474 | kblv = 0; | ||
| 475 | |||
| 476 | if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) { | ||
| 477 | pr_warning("Keyboard LED display write failed\n"); | ||
| 478 | return -EINVAL; | ||
| 479 | } | ||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | static void kled_led_set(struct led_classdev *led_cdev, | ||
| 484 | enum led_brightness value) | ||
| 485 | { | ||
| 486 | kled_led_wk = value; | ||
| 487 | queue_work(led_workqueue, &kled_led_work); | ||
| 488 | } | ||
| 489 | |||
| 490 | static void kled_led_update(struct work_struct *ignored) | ||
| 491 | { | ||
| 492 | set_kled_lvl(kled_led_wk); | ||
| 493 | } | ||
| 494 | |||
| 495 | static enum led_brightness kled_led_get(struct led_classdev *led_cdev) | ||
| 496 | { | ||
| 497 | return get_kled_lvl(); | ||
| 498 | } | ||
| 499 | |||
| 410 | static int get_lcd_state(void) | 500 | static int get_lcd_state(void) |
| 411 | { | 501 | { |
| 412 | return read_status(LCD_ON); | 502 | return read_status(LCD_ON); |
| @@ -498,7 +588,7 @@ static ssize_t show_infos(struct device *dev, | |||
| 498 | { | 588 | { |
| 499 | int len = 0; | 589 | int len = 0; |
| 500 | unsigned long long temp; | 590 | unsigned long long temp; |
| 501 | char buf[16]; //enough for all info | 591 | char buf[16]; /* enough for all info */ |
| 502 | acpi_status rv = AE_OK; | 592 | acpi_status rv = AE_OK; |
| 503 | 593 | ||
| 504 | /* | 594 | /* |
| @@ -516,7 +606,17 @@ static ssize_t show_infos(struct device *dev, | |||
| 516 | */ | 606 | */ |
| 517 | rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); | 607 | rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); |
| 518 | if (!ACPI_FAILURE(rv)) | 608 | if (!ACPI_FAILURE(rv)) |
| 519 | len += sprintf(page + len, "SFUN value : 0x%04x\n", | 609 | len += sprintf(page + len, "SFUN value : %#x\n", |
| 610 | (uint) temp); | ||
| 611 | /* | ||
| 612 | * The HWRS method return informations about the hardware. | ||
| 613 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | ||
| 614 | * The significance of others is yet to be found. | ||
| 615 | * If we don't find the method, we assume the device are present. | ||
| 616 | */ | ||
| 617 | rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp); | ||
| 618 | if (!ACPI_FAILURE(rv)) | ||
| 619 | len += sprintf(page + len, "HRWS value : %#x\n", | ||
| 520 | (uint) temp); | 620 | (uint) temp); |
| 521 | /* | 621 | /* |
| 522 | * Another value for userspace: the ASYM method returns 0x02 for | 622 | * Another value for userspace: the ASYM method returns 0x02 for |
| @@ -527,7 +627,7 @@ static ssize_t show_infos(struct device *dev, | |||
| 527 | */ | 627 | */ |
| 528 | rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); | 628 | rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); |
| 529 | if (!ACPI_FAILURE(rv)) | 629 | if (!ACPI_FAILURE(rv)) |
| 530 | len += sprintf(page + len, "ASYM value : 0x%04x\n", | 630 | len += sprintf(page + len, "ASYM value : %#x\n", |
| 531 | (uint) temp); | 631 | (uint) temp); |
| 532 | if (asus_info) { | 632 | if (asus_info) { |
| 533 | snprintf(buf, 16, "%d", asus_info->length); | 633 | snprintf(buf, 16, "%d", asus_info->length); |
| @@ -648,8 +748,10 @@ static int read_display(void) | |||
| 648 | unsigned long long value = 0; | 748 | unsigned long long value = 0; |
| 649 | acpi_status rv = AE_OK; | 749 | acpi_status rv = AE_OK; |
| 650 | 750 | ||
| 651 | /* In most of the case, we know how to set the display, but sometime | 751 | /* |
| 652 | we can't read it */ | 752 | * In most of the case, we know how to set the display, but sometime |
| 753 | * we can't read it | ||
| 754 | */ | ||
| 653 | if (display_get_handle) { | 755 | if (display_get_handle) { |
| 654 | rv = acpi_evaluate_integer(display_get_handle, NULL, | 756 | rv = acpi_evaluate_integer(display_get_handle, NULL, |
| 655 | NULL, &value); | 757 | NULL, &value); |
| @@ -1037,6 +1139,9 @@ static int asus_hotk_get_info(void) | |||
| 1037 | 1139 | ||
| 1038 | ASUS_HANDLE_INIT(ledd_set); | 1140 | ASUS_HANDLE_INIT(ledd_set); |
| 1039 | 1141 | ||
| 1142 | ASUS_HANDLE_INIT(kled_set); | ||
| 1143 | ASUS_HANDLE_INIT(kled_get); | ||
| 1144 | |||
| 1040 | /* | 1145 | /* |
| 1041 | * The HWRS method return informations about the hardware. | 1146 | * The HWRS method return informations about the hardware. |
| 1042 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | 1147 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. |
| @@ -1063,8 +1168,10 @@ static int asus_hotk_get_info(void) | |||
| 1063 | ASUS_HANDLE_INIT(display_set); | 1168 | ASUS_HANDLE_INIT(display_set); |
| 1064 | ASUS_HANDLE_INIT(display_get); | 1169 | ASUS_HANDLE_INIT(display_get); |
| 1065 | 1170 | ||
| 1066 | /* There is a lot of models with "ALSL", but a few get | 1171 | /* |
| 1067 | a real light sens, so we need to check it. */ | 1172 | * There is a lot of models with "ALSL", but a few get |
| 1173 | * a real light sens, so we need to check it. | ||
| 1174 | */ | ||
| 1068 | if (!ASUS_HANDLE_INIT(ls_switch)) | 1175 | if (!ASUS_HANDLE_INIT(ls_switch)) |
| 1069 | ASUS_HANDLE_INIT(ls_level); | 1176 | ASUS_HANDLE_INIT(ls_level); |
| 1070 | 1177 | ||
| @@ -1168,6 +1275,10 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 1168 | /* LCD Backlight is on by default */ | 1275 | /* LCD Backlight is on by default */ |
| 1169 | write_status(NULL, 1, LCD_ON); | 1276 | write_status(NULL, 1, LCD_ON); |
| 1170 | 1277 | ||
| 1278 | /* Keyboard Backlight is on by default */ | ||
| 1279 | if (kled_set_handle) | ||
| 1280 | set_kled_lvl(1); | ||
| 1281 | |||
| 1171 | /* LED display is off by default */ | 1282 | /* LED display is off by default */ |
| 1172 | hotk->ledd_status = 0xFFF; | 1283 | hotk->ledd_status = 0xFFF; |
| 1173 | 1284 | ||
| @@ -1222,6 +1333,7 @@ static void asus_led_exit(void) | |||
| 1222 | ASUS_LED_UNREGISTER(pled); | 1333 | ASUS_LED_UNREGISTER(pled); |
| 1223 | ASUS_LED_UNREGISTER(rled); | 1334 | ASUS_LED_UNREGISTER(rled); |
| 1224 | ASUS_LED_UNREGISTER(gled); | 1335 | ASUS_LED_UNREGISTER(gled); |
| 1336 | ASUS_LED_UNREGISTER(kled); | ||
| 1225 | } | 1337 | } |
| 1226 | 1338 | ||
| 1227 | static void asus_input_exit(void) | 1339 | static void asus_input_exit(void) |
| @@ -1301,13 +1413,20 @@ static int asus_led_init(struct device *dev) | |||
| 1301 | if (rv) | 1413 | if (rv) |
| 1302 | goto out4; | 1414 | goto out4; |
| 1303 | 1415 | ||
| 1416 | if (kled_set_handle && kled_get_handle) | ||
| 1417 | rv = ASUS_LED_REGISTER(kled, dev); | ||
| 1418 | if (rv) | ||
| 1419 | goto out5; | ||
| 1420 | |||
| 1304 | led_workqueue = create_singlethread_workqueue("led_workqueue"); | 1421 | led_workqueue = create_singlethread_workqueue("led_workqueue"); |
| 1305 | if (!led_workqueue) | 1422 | if (!led_workqueue) |
| 1306 | goto out5; | 1423 | goto out6; |
| 1307 | 1424 | ||
| 1308 | return 0; | 1425 | return 0; |
| 1309 | out5: | 1426 | out6: |
| 1310 | rv = -ENOMEM; | 1427 | rv = -ENOMEM; |
| 1428 | ASUS_LED_UNREGISTER(kled); | ||
| 1429 | out5: | ||
| 1311 | ASUS_LED_UNREGISTER(gled); | 1430 | ASUS_LED_UNREGISTER(gled); |
| 1312 | out4: | 1431 | out4: |
| 1313 | ASUS_LED_UNREGISTER(pled); | 1432 | ASUS_LED_UNREGISTER(pled); |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 222ffb892f22..da3c08b3dcc1 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -142,18 +142,28 @@ struct eeepc_hotk { | |||
| 142 | struct rfkill *wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
| 143 | struct rfkill *bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
| 144 | struct rfkill *wwan3g_rfkill; | 144 | struct rfkill *wwan3g_rfkill; |
| 145 | struct rfkill *wimax_rfkill; | ||
| 145 | struct hotplug_slot *hotplug_slot; | 146 | struct hotplug_slot *hotplug_slot; |
| 146 | struct work_struct hotplug_work; | 147 | struct mutex hotplug_lock; |
| 147 | }; | 148 | }; |
| 148 | 149 | ||
| 149 | /* The actual device the driver binds to */ | 150 | /* The actual device the driver binds to */ |
| 150 | static struct eeepc_hotk *ehotk; | 151 | static struct eeepc_hotk *ehotk; |
| 151 | 152 | ||
| 152 | /* Platform device/driver */ | 153 | /* Platform device/driver */ |
| 154 | static int eeepc_hotk_thaw(struct device *device); | ||
| 155 | static int eeepc_hotk_restore(struct device *device); | ||
| 156 | |||
| 157 | static struct dev_pm_ops eeepc_pm_ops = { | ||
| 158 | .thaw = eeepc_hotk_thaw, | ||
| 159 | .restore = eeepc_hotk_restore, | ||
| 160 | }; | ||
| 161 | |||
| 153 | static struct platform_driver platform_driver = { | 162 | static struct platform_driver platform_driver = { |
| 154 | .driver = { | 163 | .driver = { |
| 155 | .name = EEEPC_HOTK_FILE, | 164 | .name = EEEPC_HOTK_FILE, |
| 156 | .owner = THIS_MODULE, | 165 | .owner = THIS_MODULE, |
| 166 | .pm = &eeepc_pm_ops, | ||
| 157 | } | 167 | } |
| 158 | }; | 168 | }; |
| 159 | 169 | ||
| @@ -192,7 +202,6 @@ static struct key_entry eeepc_keymap[] = { | |||
| 192 | */ | 202 | */ |
| 193 | static int eeepc_hotk_add(struct acpi_device *device); | 203 | static int eeepc_hotk_add(struct acpi_device *device); |
| 194 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | 204 | static int eeepc_hotk_remove(struct acpi_device *device, int type); |
| 195 | static int eeepc_hotk_resume(struct acpi_device *device); | ||
| 196 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event); | 205 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event); |
| 197 | 206 | ||
| 198 | static const struct acpi_device_id eeepc_device_ids[] = { | 207 | static const struct acpi_device_id eeepc_device_ids[] = { |
| @@ -209,7 +218,6 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
| 209 | .ops = { | 218 | .ops = { |
| 210 | .add = eeepc_hotk_add, | 219 | .add = eeepc_hotk_add, |
| 211 | .remove = eeepc_hotk_remove, | 220 | .remove = eeepc_hotk_remove, |
| 212 | .resume = eeepc_hotk_resume, | ||
| 213 | .notify = eeepc_hotk_notify, | 221 | .notify = eeepc_hotk_notify, |
| 214 | }, | 222 | }, |
| 215 | }; | 223 | }; |
| @@ -579,7 +587,6 @@ static void cmsg_quirks(void) | |||
| 579 | 587 | ||
| 580 | static int eeepc_hotk_check(void) | 588 | static int eeepc_hotk_check(void) |
| 581 | { | 589 | { |
| 582 | const struct key_entry *key; | ||
| 583 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 590 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 584 | int result; | 591 | int result; |
| 585 | 592 | ||
| @@ -604,31 +611,6 @@ static int eeepc_hotk_check(void) | |||
| 604 | pr_info("Get control methods supported: 0x%x\n", | 611 | pr_info("Get control methods supported: 0x%x\n", |
| 605 | ehotk->cm_supported); | 612 | ehotk->cm_supported); |
| 606 | } | 613 | } |
| 607 | ehotk->inputdev = input_allocate_device(); | ||
| 608 | if (!ehotk->inputdev) { | ||
| 609 | pr_info("Unable to allocate input device\n"); | ||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | ||
| 613 | ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; | ||
| 614 | ehotk->inputdev->id.bustype = BUS_HOST; | ||
| 615 | ehotk->inputdev->getkeycode = eeepc_getkeycode; | ||
| 616 | ehotk->inputdev->setkeycode = eeepc_setkeycode; | ||
| 617 | |||
| 618 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
| 619 | switch (key->type) { | ||
| 620 | case KE_KEY: | ||
| 621 | set_bit(EV_KEY, ehotk->inputdev->evbit); | ||
| 622 | set_bit(key->keycode, ehotk->inputdev->keybit); | ||
| 623 | break; | ||
| 624 | } | ||
| 625 | } | ||
| 626 | result = input_register_device(ehotk->inputdev); | ||
| 627 | if (result) { | ||
| 628 | pr_info("Unable to register input device\n"); | ||
| 629 | input_free_device(ehotk->inputdev); | ||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | } else { | 614 | } else { |
| 633 | pr_err("Hotkey device not present, aborting\n"); | 615 | pr_err("Hotkey device not present, aborting\n"); |
| 634 | return -EINVAL; | 616 | return -EINVAL; |
| @@ -661,40 +643,48 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | |||
| 661 | return 0; | 643 | return 0; |
| 662 | } | 644 | } |
| 663 | 645 | ||
| 664 | static void eeepc_hotplug_work(struct work_struct *work) | 646 | static void eeepc_rfkill_hotplug(void) |
| 665 | { | 647 | { |
| 666 | struct pci_dev *dev; | 648 | struct pci_dev *dev; |
| 667 | struct pci_bus *bus = pci_find_bus(0, 1); | 649 | struct pci_bus *bus; |
| 668 | bool blocked; | 650 | bool blocked = eeepc_wlan_rfkill_blocked(); |
| 669 | 651 | ||
| 670 | if (!bus) { | 652 | if (ehotk->wlan_rfkill) |
| 671 | pr_warning("Unable to find PCI bus 1?\n"); | 653 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
| 672 | return; | ||
| 673 | } | ||
| 674 | 654 | ||
| 675 | blocked = eeepc_wlan_rfkill_blocked(); | 655 | mutex_lock(&ehotk->hotplug_lock); |
| 676 | if (!blocked) { | 656 | |
| 677 | dev = pci_get_slot(bus, 0); | 657 | if (ehotk->hotplug_slot) { |
| 678 | if (dev) { | 658 | bus = pci_find_bus(0, 1); |
| 679 | /* Device already present */ | 659 | if (!bus) { |
| 680 | pci_dev_put(dev); | 660 | pr_warning("Unable to find PCI bus 1?\n"); |
| 681 | return; | 661 | goto out_unlock; |
| 682 | } | ||
| 683 | dev = pci_scan_single_device(bus, 0); | ||
| 684 | if (dev) { | ||
| 685 | pci_bus_assign_resources(bus); | ||
| 686 | if (pci_bus_add_device(dev)) | ||
| 687 | pr_err("Unable to hotplug wifi\n"); | ||
| 688 | } | 662 | } |
| 689 | } else { | 663 | |
| 690 | dev = pci_get_slot(bus, 0); | 664 | if (!blocked) { |
| 691 | if (dev) { | 665 | dev = pci_get_slot(bus, 0); |
| 692 | pci_remove_bus_device(dev); | 666 | if (dev) { |
| 693 | pci_dev_put(dev); | 667 | /* Device already present */ |
| 668 | pci_dev_put(dev); | ||
| 669 | goto out_unlock; | ||
| 670 | } | ||
| 671 | dev = pci_scan_single_device(bus, 0); | ||
| 672 | if (dev) { | ||
| 673 | pci_bus_assign_resources(bus); | ||
| 674 | if (pci_bus_add_device(dev)) | ||
| 675 | pr_err("Unable to hotplug wifi\n"); | ||
| 676 | } | ||
| 677 | } else { | ||
| 678 | dev = pci_get_slot(bus, 0); | ||
| 679 | if (dev) { | ||
| 680 | pci_remove_bus_device(dev); | ||
| 681 | pci_dev_put(dev); | ||
| 682 | } | ||
| 694 | } | 683 | } |
| 695 | } | 684 | } |
| 696 | 685 | ||
| 697 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); | 686 | out_unlock: |
| 687 | mutex_unlock(&ehotk->hotplug_lock); | ||
| 698 | } | 688 | } |
| 699 | 689 | ||
| 700 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 690 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
| @@ -702,7 +692,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
| 702 | if (event != ACPI_NOTIFY_BUS_CHECK) | 692 | if (event != ACPI_NOTIFY_BUS_CHECK) |
| 703 | return; | 693 | return; |
| 704 | 694 | ||
| 705 | schedule_work(&ehotk->hotplug_work); | 695 | eeepc_rfkill_hotplug(); |
| 706 | } | 696 | } |
| 707 | 697 | ||
| 708 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) | 698 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) |
| @@ -839,66 +829,38 @@ error_slot: | |||
| 839 | return ret; | 829 | return ret; |
| 840 | } | 830 | } |
| 841 | 831 | ||
| 842 | static int eeepc_hotk_add(struct acpi_device *device) | 832 | static int eeepc_hotk_thaw(struct device *device) |
| 843 | { | ||
| 844 | int result; | ||
| 845 | |||
| 846 | if (!device) | ||
| 847 | return -EINVAL; | ||
| 848 | pr_notice(EEEPC_HOTK_NAME "\n"); | ||
| 849 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | ||
| 850 | if (!ehotk) | ||
| 851 | return -ENOMEM; | ||
| 852 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; | ||
| 853 | ehotk->handle = device->handle; | ||
| 854 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | ||
| 855 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
| 856 | device->driver_data = ehotk; | ||
| 857 | ehotk->device = device; | ||
| 858 | result = eeepc_hotk_check(); | ||
| 859 | if (result) | ||
| 860 | goto ehotk_fail; | ||
| 861 | |||
| 862 | return 0; | ||
| 863 | |||
| 864 | ehotk_fail: | ||
| 865 | kfree(ehotk); | ||
| 866 | ehotk = NULL; | ||
| 867 | |||
| 868 | return result; | ||
| 869 | } | ||
| 870 | |||
| 871 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
| 872 | { | ||
| 873 | if (!device || !acpi_driver_data(device)) | ||
| 874 | return -EINVAL; | ||
| 875 | |||
| 876 | kfree(ehotk); | ||
| 877 | return 0; | ||
| 878 | } | ||
| 879 | |||
| 880 | static int eeepc_hotk_resume(struct acpi_device *device) | ||
| 881 | { | 833 | { |
| 882 | if (ehotk->wlan_rfkill) { | 834 | if (ehotk->wlan_rfkill) { |
| 883 | bool wlan; | 835 | bool wlan; |
| 884 | 836 | ||
| 885 | /* Workaround - it seems that _PTS disables the wireless | 837 | /* |
| 886 | without notification or changing the value read by WLAN. | 838 | * Work around bios bug - acpi _PTS turns off the wireless led |
| 887 | Normally this is fine because the correct value is restored | 839 | * during suspend. Normally it restores it on resume, but |
| 888 | from the non-volatile storage on resume, but we need to do | 840 | * we should kick it ourselves in case hibernation is aborted. |
| 889 | it ourself if case suspend is aborted, or we lose wireless. | ||
| 890 | */ | 841 | */ |
| 891 | wlan = get_acpi(CM_ASL_WLAN); | 842 | wlan = get_acpi(CM_ASL_WLAN); |
| 892 | set_acpi(CM_ASL_WLAN, wlan); | 843 | set_acpi(CM_ASL_WLAN, wlan); |
| 844 | } | ||
| 893 | 845 | ||
| 894 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); | 846 | return 0; |
| 847 | } | ||
| 895 | 848 | ||
| 896 | schedule_work(&ehotk->hotplug_work); | 849 | static int eeepc_hotk_restore(struct device *device) |
| 897 | } | 850 | { |
| 851 | /* Refresh both wlan rfkill state and pci hotplug */ | ||
| 852 | if (ehotk->wlan_rfkill) | ||
| 853 | eeepc_rfkill_hotplug(); | ||
| 898 | 854 | ||
| 899 | if (ehotk->bluetooth_rfkill) | 855 | if (ehotk->bluetooth_rfkill) |
| 900 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, | 856 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
| 901 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 857 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
| 858 | if (ehotk->wwan3g_rfkill) | ||
| 859 | rfkill_set_sw_state(ehotk->wwan3g_rfkill, | ||
| 860 | get_acpi(CM_ASL_3G) != 1); | ||
| 861 | if (ehotk->wimax_rfkill) | ||
| 862 | rfkill_set_sw_state(ehotk->wimax_rfkill, | ||
| 863 | get_acpi(CM_ASL_WIMAX) != 1); | ||
| 902 | 864 | ||
| 903 | return 0; | 865 | return 0; |
| 904 | } | 866 | } |
| @@ -1019,16 +981,37 @@ static void eeepc_backlight_exit(void) | |||
| 1019 | 981 | ||
| 1020 | static void eeepc_rfkill_exit(void) | 982 | static void eeepc_rfkill_exit(void) |
| 1021 | { | 983 | { |
| 984 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5"); | ||
| 1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | 985 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
| 1023 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | 986 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
| 1024 | if (ehotk->wlan_rfkill) | 987 | if (ehotk->wlan_rfkill) { |
| 1025 | rfkill_unregister(ehotk->wlan_rfkill); | 988 | rfkill_unregister(ehotk->wlan_rfkill); |
| 1026 | if (ehotk->bluetooth_rfkill) | 989 | rfkill_destroy(ehotk->wlan_rfkill); |
| 1027 | rfkill_unregister(ehotk->bluetooth_rfkill); | 990 | ehotk->wlan_rfkill = NULL; |
| 1028 | if (ehotk->wwan3g_rfkill) | 991 | } |
| 1029 | rfkill_unregister(ehotk->wwan3g_rfkill); | 992 | /* |
| 993 | * Refresh pci hotplug in case the rfkill state was changed after | ||
| 994 | * eeepc_unregister_rfkill_notifier() | ||
| 995 | */ | ||
| 996 | eeepc_rfkill_hotplug(); | ||
| 1030 | if (ehotk->hotplug_slot) | 997 | if (ehotk->hotplug_slot) |
| 1031 | pci_hp_deregister(ehotk->hotplug_slot); | 998 | pci_hp_deregister(ehotk->hotplug_slot); |
| 999 | |||
| 1000 | if (ehotk->bluetooth_rfkill) { | ||
| 1001 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
| 1002 | rfkill_destroy(ehotk->bluetooth_rfkill); | ||
| 1003 | ehotk->bluetooth_rfkill = NULL; | ||
| 1004 | } | ||
| 1005 | if (ehotk->wwan3g_rfkill) { | ||
| 1006 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
| 1007 | rfkill_destroy(ehotk->wwan3g_rfkill); | ||
| 1008 | ehotk->wwan3g_rfkill = NULL; | ||
| 1009 | } | ||
| 1010 | if (ehotk->wimax_rfkill) { | ||
| 1011 | rfkill_unregister(ehotk->wimax_rfkill); | ||
| 1012 | rfkill_destroy(ehotk->wimax_rfkill); | ||
| 1013 | ehotk->wimax_rfkill = NULL; | ||
| 1014 | } | ||
| 1032 | } | 1015 | } |
| 1033 | 1016 | ||
| 1034 | static void eeepc_input_exit(void) | 1017 | static void eeepc_input_exit(void) |
| @@ -1050,19 +1033,6 @@ static void eeepc_hwmon_exit(void) | |||
| 1050 | eeepc_hwmon_device = NULL; | 1033 | eeepc_hwmon_device = NULL; |
| 1051 | } | 1034 | } |
| 1052 | 1035 | ||
| 1053 | static void __exit eeepc_laptop_exit(void) | ||
| 1054 | { | ||
| 1055 | eeepc_backlight_exit(); | ||
| 1056 | eeepc_rfkill_exit(); | ||
| 1057 | eeepc_input_exit(); | ||
| 1058 | eeepc_hwmon_exit(); | ||
| 1059 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
| 1060 | sysfs_remove_group(&platform_device->dev.kobj, | ||
| 1061 | &platform_attribute_group); | ||
| 1062 | platform_device_unregister(platform_device); | ||
| 1063 | platform_driver_unregister(&platform_driver); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | static int eeepc_new_rfkill(struct rfkill **rfkill, | 1036 | static int eeepc_new_rfkill(struct rfkill **rfkill, |
| 1067 | const char *name, struct device *dev, | 1037 | const char *name, struct device *dev, |
| 1068 | enum rfkill_type type, int cm) | 1038 | enum rfkill_type type, int cm) |
| @@ -1094,10 +1064,7 @@ static int eeepc_rfkill_init(struct device *dev) | |||
| 1094 | { | 1064 | { |
| 1095 | int result = 0; | 1065 | int result = 0; |
| 1096 | 1066 | ||
| 1097 | INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work); | 1067 | mutex_init(&ehotk->hotplug_lock); |
| 1098 | |||
| 1099 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 1100 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 1101 | 1068 | ||
| 1102 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | 1069 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, |
| 1103 | "eeepc-wlan", dev, | 1070 | "eeepc-wlan", dev, |
| @@ -1120,6 +1087,13 @@ static int eeepc_rfkill_init(struct device *dev) | |||
| 1120 | if (result && result != -ENODEV) | 1087 | if (result && result != -ENODEV) |
| 1121 | goto exit; | 1088 | goto exit; |
| 1122 | 1089 | ||
| 1090 | result = eeepc_new_rfkill(&ehotk->wimax_rfkill, | ||
| 1091 | "eeepc-wimax", dev, | ||
| 1092 | RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); | ||
| 1093 | |||
| 1094 | if (result && result != -ENODEV) | ||
| 1095 | goto exit; | ||
| 1096 | |||
| 1123 | result = eeepc_setup_pci_hotplug(); | 1097 | result = eeepc_setup_pci_hotplug(); |
| 1124 | /* | 1098 | /* |
| 1125 | * If we get -EBUSY then something else is handling the PCI hotplug - | 1099 | * If we get -EBUSY then something else is handling the PCI hotplug - |
| @@ -1128,6 +1102,15 @@ static int eeepc_rfkill_init(struct device *dev) | |||
| 1128 | if (result == -EBUSY) | 1102 | if (result == -EBUSY) |
| 1129 | result = 0; | 1103 | result = 0; |
| 1130 | 1104 | ||
| 1105 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); | ||
| 1106 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 1107 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 1108 | /* | ||
| 1109 | * Refresh pci hotplug in case the rfkill state was changed during | ||
| 1110 | * setup. | ||
| 1111 | */ | ||
| 1112 | eeepc_rfkill_hotplug(); | ||
| 1113 | |||
| 1131 | exit: | 1114 | exit: |
| 1132 | if (result && result != -ENODEV) | 1115 | if (result && result != -ENODEV) |
| 1133 | eeepc_rfkill_exit(); | 1116 | eeepc_rfkill_exit(); |
| @@ -1172,21 +1155,61 @@ static int eeepc_hwmon_init(struct device *dev) | |||
| 1172 | return result; | 1155 | return result; |
| 1173 | } | 1156 | } |
| 1174 | 1157 | ||
| 1175 | static int __init eeepc_laptop_init(void) | 1158 | static int eeepc_input_init(struct device *dev) |
| 1176 | { | 1159 | { |
| 1177 | struct device *dev; | 1160 | const struct key_entry *key; |
| 1178 | int result; | 1161 | int result; |
| 1179 | 1162 | ||
| 1180 | if (acpi_disabled) | 1163 | ehotk->inputdev = input_allocate_device(); |
| 1181 | return -ENODEV; | 1164 | if (!ehotk->inputdev) { |
| 1182 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | 1165 | pr_info("Unable to allocate input device\n"); |
| 1183 | if (result < 0) | 1166 | return -ENOMEM; |
| 1167 | } | ||
| 1168 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | ||
| 1169 | ehotk->inputdev->dev.parent = dev; | ||
| 1170 | ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; | ||
| 1171 | ehotk->inputdev->id.bustype = BUS_HOST; | ||
| 1172 | ehotk->inputdev->getkeycode = eeepc_getkeycode; | ||
| 1173 | ehotk->inputdev->setkeycode = eeepc_setkeycode; | ||
| 1174 | |||
| 1175 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
| 1176 | switch (key->type) { | ||
| 1177 | case KE_KEY: | ||
| 1178 | set_bit(EV_KEY, ehotk->inputdev->evbit); | ||
| 1179 | set_bit(key->keycode, ehotk->inputdev->keybit); | ||
| 1180 | break; | ||
| 1181 | } | ||
| 1182 | } | ||
| 1183 | result = input_register_device(ehotk->inputdev); | ||
| 1184 | if (result) { | ||
| 1185 | pr_info("Unable to register input device\n"); | ||
| 1186 | input_free_device(ehotk->inputdev); | ||
| 1184 | return result; | 1187 | return result; |
| 1185 | if (!ehotk) { | ||
| 1186 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
| 1187 | return -ENODEV; | ||
| 1188 | } | 1188 | } |
| 1189 | return 0; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | static int eeepc_hotk_add(struct acpi_device *device) | ||
| 1193 | { | ||
| 1194 | struct device *dev; | ||
| 1195 | int result; | ||
| 1189 | 1196 | ||
| 1197 | if (!device) | ||
| 1198 | return -EINVAL; | ||
| 1199 | pr_notice(EEEPC_HOTK_NAME "\n"); | ||
| 1200 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | ||
| 1201 | if (!ehotk) | ||
| 1202 | return -ENOMEM; | ||
| 1203 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; | ||
| 1204 | ehotk->handle = device->handle; | ||
| 1205 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | ||
| 1206 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
| 1207 | device->driver_data = ehotk; | ||
| 1208 | ehotk->device = device; | ||
| 1209 | |||
| 1210 | result = eeepc_hotk_check(); | ||
| 1211 | if (result) | ||
| 1212 | goto fail_platform_driver; | ||
| 1190 | eeepc_enable_camera(); | 1213 | eeepc_enable_camera(); |
| 1191 | 1214 | ||
| 1192 | /* Register platform stuff */ | 1215 | /* Register platform stuff */ |
| @@ -1216,6 +1239,10 @@ static int __init eeepc_laptop_init(void) | |||
| 1216 | pr_info("Backlight controlled by ACPI video " | 1239 | pr_info("Backlight controlled by ACPI video " |
| 1217 | "driver\n"); | 1240 | "driver\n"); |
| 1218 | 1241 | ||
| 1242 | result = eeepc_input_init(dev); | ||
| 1243 | if (result) | ||
| 1244 | goto fail_input; | ||
| 1245 | |||
| 1219 | result = eeepc_hwmon_init(dev); | 1246 | result = eeepc_hwmon_init(dev); |
| 1220 | if (result) | 1247 | if (result) |
| 1221 | goto fail_hwmon; | 1248 | goto fail_hwmon; |
| @@ -1225,9 +1252,12 @@ static int __init eeepc_laptop_init(void) | |||
| 1225 | goto fail_rfkill; | 1252 | goto fail_rfkill; |
| 1226 | 1253 | ||
| 1227 | return 0; | 1254 | return 0; |
| 1255 | |||
| 1228 | fail_rfkill: | 1256 | fail_rfkill: |
| 1229 | eeepc_hwmon_exit(); | 1257 | eeepc_hwmon_exit(); |
| 1230 | fail_hwmon: | 1258 | fail_hwmon: |
| 1259 | eeepc_input_exit(); | ||
| 1260 | fail_input: | ||
| 1231 | eeepc_backlight_exit(); | 1261 | eeepc_backlight_exit(); |
| 1232 | fail_backlight: | 1262 | fail_backlight: |
| 1233 | sysfs_remove_group(&platform_device->dev.kobj, | 1263 | sysfs_remove_group(&platform_device->dev.kobj, |
| @@ -1239,9 +1269,49 @@ fail_platform_device2: | |||
| 1239 | fail_platform_device1: | 1269 | fail_platform_device1: |
| 1240 | platform_driver_unregister(&platform_driver); | 1270 | platform_driver_unregister(&platform_driver); |
| 1241 | fail_platform_driver: | 1271 | fail_platform_driver: |
| 1242 | eeepc_input_exit(); | 1272 | kfree(ehotk); |
| 1273 | |||
| 1243 | return result; | 1274 | return result; |
| 1244 | } | 1275 | } |
| 1245 | 1276 | ||
| 1277 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
| 1278 | { | ||
| 1279 | if (!device || !acpi_driver_data(device)) | ||
| 1280 | return -EINVAL; | ||
| 1281 | |||
| 1282 | eeepc_backlight_exit(); | ||
| 1283 | eeepc_rfkill_exit(); | ||
| 1284 | eeepc_input_exit(); | ||
| 1285 | eeepc_hwmon_exit(); | ||
| 1286 | sysfs_remove_group(&platform_device->dev.kobj, | ||
| 1287 | &platform_attribute_group); | ||
| 1288 | platform_device_unregister(platform_device); | ||
| 1289 | platform_driver_unregister(&platform_driver); | ||
| 1290 | |||
| 1291 | kfree(ehotk); | ||
| 1292 | return 0; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | static int __init eeepc_laptop_init(void) | ||
| 1296 | { | ||
| 1297 | int result; | ||
| 1298 | |||
| 1299 | if (acpi_disabled) | ||
| 1300 | return -ENODEV; | ||
| 1301 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | ||
| 1302 | if (result < 0) | ||
| 1303 | return result; | ||
| 1304 | if (!ehotk) { | ||
| 1305 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
| 1306 | return -ENODEV; | ||
| 1307 | } | ||
| 1308 | return 0; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static void __exit eeepc_laptop_exit(void) | ||
| 1312 | { | ||
| 1313 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
| 1314 | } | ||
| 1315 | |||
| 1246 | module_init(eeepc_laptop_init); | 1316 | module_init(eeepc_laptop_init); |
| 1247 | module_exit(eeepc_laptop_exit); | 1317 | module_exit(eeepc_laptop_exit); |
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 218b9a16ac3f..f35aee5c2149 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c | |||
| @@ -66,11 +66,11 @@ | |||
| 66 | #include <linux/kfifo.h> | 66 | #include <linux/kfifo.h> |
| 67 | #include <linux/video_output.h> | 67 | #include <linux/video_output.h> |
| 68 | #include <linux/platform_device.h> | 68 | #include <linux/platform_device.h> |
| 69 | #ifdef CONFIG_LEDS_CLASS | 69 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) |
| 70 | #include <linux/leds.h> | 70 | #include <linux/leds.h> |
| 71 | #endif | 71 | #endif |
| 72 | 72 | ||
| 73 | #define FUJITSU_DRIVER_VERSION "0.5.0" | 73 | #define FUJITSU_DRIVER_VERSION "0.6.0" |
| 74 | 74 | ||
| 75 | #define FUJITSU_LCD_N_LEVELS 8 | 75 | #define FUJITSU_LCD_N_LEVELS 8 |
| 76 | 76 | ||
| @@ -96,7 +96,7 @@ | |||
| 96 | /* FUNC interface - responses */ | 96 | /* FUNC interface - responses */ |
| 97 | #define UNSUPPORTED_CMD 0x80000000 | 97 | #define UNSUPPORTED_CMD 0x80000000 |
| 98 | 98 | ||
| 99 | #ifdef CONFIG_LEDS_CLASS | 99 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) |
| 100 | /* FUNC interface - LED control */ | 100 | /* FUNC interface - LED control */ |
| 101 | #define FUNC_LED_OFF 0x1 | 101 | #define FUNC_LED_OFF 0x1 |
| 102 | #define FUNC_LED_ON 0x30001 | 102 | #define FUNC_LED_ON 0x30001 |
| @@ -176,7 +176,7 @@ static struct fujitsu_hotkey_t *fujitsu_hotkey; | |||
| 176 | 176 | ||
| 177 | static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event); | 177 | static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event); |
| 178 | 178 | ||
| 179 | #ifdef CONFIG_LEDS_CLASS | 179 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) |
| 180 | static enum led_brightness logolamp_get(struct led_classdev *cdev); | 180 | static enum led_brightness logolamp_get(struct led_classdev *cdev); |
| 181 | static void logolamp_set(struct led_classdev *cdev, | 181 | static void logolamp_set(struct led_classdev *cdev, |
| 182 | enum led_brightness brightness); | 182 | enum led_brightness brightness); |
| @@ -257,7 +257,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2) | |||
| 257 | return out_obj.integer.value; | 257 | return out_obj.integer.value; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | #ifdef CONFIG_LEDS_CLASS | 260 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) |
| 261 | /* LED class callbacks */ | 261 | /* LED class callbacks */ |
| 262 | 262 | ||
| 263 | static void logolamp_set(struct led_classdev *cdev, | 263 | static void logolamp_set(struct led_classdev *cdev, |
| @@ -324,9 +324,6 @@ static int set_lcd_level(int level) | |||
| 324 | if (level < 0 || level >= fujitsu->max_brightness) | 324 | if (level < 0 || level >= fujitsu->max_brightness) |
| 325 | return -EINVAL; | 325 | return -EINVAL; |
| 326 | 326 | ||
| 327 | if (!fujitsu) | ||
| 328 | return -EINVAL; | ||
| 329 | |||
| 330 | status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle); | 327 | status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle); |
| 331 | if (ACPI_FAILURE(status)) { | 328 | if (ACPI_FAILURE(status)) { |
| 332 | vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n"); | 329 | vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n"); |
| @@ -355,9 +352,6 @@ static int set_lcd_level_alt(int level) | |||
| 355 | if (level < 0 || level >= fujitsu->max_brightness) | 352 | if (level < 0 || level >= fujitsu->max_brightness) |
| 356 | return -EINVAL; | 353 | return -EINVAL; |
| 357 | 354 | ||
| 358 | if (!fujitsu) | ||
| 359 | return -EINVAL; | ||
| 360 | |||
| 361 | status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle); | 355 | status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle); |
| 362 | if (ACPI_FAILURE(status)) { | 356 | if (ACPI_FAILURE(status)) { |
| 363 | vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n"); | 357 | vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n"); |
| @@ -697,10 +691,10 @@ static int acpi_fujitsu_add(struct acpi_device *device) | |||
| 697 | result = acpi_bus_get_power(fujitsu->acpi_handle, &state); | 691 | result = acpi_bus_get_power(fujitsu->acpi_handle, &state); |
| 698 | if (result) { | 692 | if (result) { |
| 699 | printk(KERN_ERR "Error reading power state\n"); | 693 | printk(KERN_ERR "Error reading power state\n"); |
| 700 | goto end; | 694 | goto err_unregister_input_dev; |
| 701 | } | 695 | } |
| 702 | 696 | ||
| 703 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | 697 | printk(KERN_INFO "ACPI: %s [%s] (%s)\n", |
| 704 | acpi_device_name(device), acpi_device_bid(device), | 698 | acpi_device_name(device), acpi_device_bid(device), |
| 705 | !device->power.state ? "on" : "off"); | 699 | !device->power.state ? "on" : "off"); |
| 706 | 700 | ||
| @@ -728,25 +722,22 @@ static int acpi_fujitsu_add(struct acpi_device *device) | |||
| 728 | 722 | ||
| 729 | return result; | 723 | return result; |
| 730 | 724 | ||
| 731 | end: | 725 | err_unregister_input_dev: |
| 726 | input_unregister_device(input); | ||
| 732 | err_free_input_dev: | 727 | err_free_input_dev: |
| 733 | input_free_device(input); | 728 | input_free_device(input); |
| 734 | err_stop: | 729 | err_stop: |
| 735 | |||
| 736 | return result; | 730 | return result; |
| 737 | } | 731 | } |
| 738 | 732 | ||
| 739 | static int acpi_fujitsu_remove(struct acpi_device *device, int type) | 733 | static int acpi_fujitsu_remove(struct acpi_device *device, int type) |
| 740 | { | 734 | { |
| 741 | struct fujitsu_t *fujitsu = NULL; | 735 | struct fujitsu_t *fujitsu = acpi_driver_data(device); |
| 736 | struct input_dev *input = fujitsu->input; | ||
| 742 | 737 | ||
| 743 | if (!device || !acpi_driver_data(device)) | 738 | input_unregister_device(input); |
| 744 | return -EINVAL; | ||
| 745 | 739 | ||
| 746 | fujitsu = acpi_driver_data(device); | 740 | input_free_device(input); |
| 747 | |||
| 748 | if (!device || !acpi_driver_data(device)) | ||
| 749 | return -EINVAL; | ||
| 750 | 741 | ||
| 751 | fujitsu->acpi_handle = NULL; | 742 | fujitsu->acpi_handle = NULL; |
| 752 | 743 | ||
| @@ -871,10 +862,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
| 871 | result = acpi_bus_get_power(fujitsu_hotkey->acpi_handle, &state); | 862 | result = acpi_bus_get_power(fujitsu_hotkey->acpi_handle, &state); |
| 872 | if (result) { | 863 | if (result) { |
| 873 | printk(KERN_ERR "Error reading power state\n"); | 864 | printk(KERN_ERR "Error reading power state\n"); |
| 874 | goto end; | 865 | goto err_unregister_input_dev; |
| 875 | } | 866 | } |
| 876 | 867 | ||
| 877 | printk(KERN_INFO PREFIX "%s [%s] (%s)\n", | 868 | printk(KERN_INFO "ACPI: %s [%s] (%s)\n", |
| 878 | acpi_device_name(device), acpi_device_bid(device), | 869 | acpi_device_name(device), acpi_device_bid(device), |
| 879 | !device->power.state ? "on" : "off"); | 870 | !device->power.state ? "on" : "off"); |
| 880 | 871 | ||
| @@ -911,7 +902,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
| 911 | printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n", | 902 | printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n", |
| 912 | call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); | 903 | call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); |
| 913 | 904 | ||
| 914 | #ifdef CONFIG_LEDS_CLASS | 905 | #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) |
| 915 | if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { | 906 | if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { |
| 916 | result = led_classdev_register(&fujitsu->pf_device->dev, | 907 | result = led_classdev_register(&fujitsu->pf_device->dev, |
| 917 | &logolamp_led); | 908 | &logolamp_led); |
| @@ -934,33 +925,41 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
| 934 | "LED handler for keyboard lamps, error %i\n", result); | 925 | "LED handler for keyboard lamps, error %i\n", result); |
| 935 | } | 926 | } |
| 936 | } | 927 | } |
| 937 | #endif | 928 | #endif |
| 938 | 929 | ||
| 939 | return result; | 930 | return result; |
| 940 | 931 | ||
| 941 | end: | 932 | err_unregister_input_dev: |
| 933 | input_unregister_device(input); | ||
| 942 | err_free_input_dev: | 934 | err_free_input_dev: |
| 943 | input_free_device(input); | 935 | input_free_device(input); |
| 944 | err_free_fifo: | 936 | err_free_fifo: |
| 945 | kfifo_free(fujitsu_hotkey->fifo); | 937 | kfifo_free(fujitsu_hotkey->fifo); |
| 946 | err_stop: | 938 | err_stop: |
| 947 | |||
| 948 | return result; | 939 | return result; |
| 949 | } | 940 | } |
| 950 | 941 | ||
| 951 | static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) | 942 | static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) |
| 952 | { | 943 | { |
| 953 | struct fujitsu_hotkey_t *fujitsu_hotkey = NULL; | 944 | struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device); |
| 945 | struct input_dev *input = fujitsu_hotkey->input; | ||
| 954 | 946 | ||
| 955 | if (!device || !acpi_driver_data(device)) | 947 | #ifdef CONFIG_LEDS_CLASS |
| 956 | return -EINVAL; | 948 | if (fujitsu_hotkey->logolamp_registered) |
| 949 | led_classdev_unregister(&logolamp_led); | ||
| 957 | 950 | ||
| 958 | fujitsu_hotkey = acpi_driver_data(device); | 951 | if (fujitsu_hotkey->kblamps_registered) |
| 952 | led_classdev_unregister(&kblamps_led); | ||
| 953 | #endif | ||
| 959 | 954 | ||
| 960 | fujitsu_hotkey->acpi_handle = NULL; | 955 | input_unregister_device(input); |
| 956 | |||
| 957 | input_free_device(input); | ||
| 961 | 958 | ||
| 962 | kfifo_free(fujitsu_hotkey->fifo); | 959 | kfifo_free(fujitsu_hotkey->fifo); |
| 963 | 960 | ||
| 961 | fujitsu_hotkey->acpi_handle = NULL; | ||
| 962 | |||
| 964 | return 0; | 963 | return 0; |
| 965 | } | 964 | } |
| 966 | 965 | ||
| @@ -1130,8 +1129,11 @@ static int __init fujitsu_init(void) | |||
| 1130 | fujitsu->bl_device = | 1129 | fujitsu->bl_device = |
| 1131 | backlight_device_register("fujitsu-laptop", NULL, NULL, | 1130 | backlight_device_register("fujitsu-laptop", NULL, NULL, |
| 1132 | &fujitsubl_ops); | 1131 | &fujitsubl_ops); |
| 1133 | if (IS_ERR(fujitsu->bl_device)) | 1132 | if (IS_ERR(fujitsu->bl_device)) { |
| 1134 | return PTR_ERR(fujitsu->bl_device); | 1133 | ret = PTR_ERR(fujitsu->bl_device); |
| 1134 | fujitsu->bl_device = NULL; | ||
| 1135 | goto fail_sysfs_group; | ||
| 1136 | } | ||
| 1135 | max_brightness = fujitsu->max_brightness; | 1137 | max_brightness = fujitsu->max_brightness; |
| 1136 | fujitsu->bl_device->props.max_brightness = max_brightness - 1; | 1138 | fujitsu->bl_device->props.max_brightness = max_brightness - 1; |
| 1137 | fujitsu->bl_device->props.brightness = fujitsu->brightness_level; | 1139 | fujitsu->bl_device->props.brightness = fujitsu->brightness_level; |
| @@ -1171,32 +1173,22 @@ static int __init fujitsu_init(void) | |||
| 1171 | return 0; | 1173 | return 0; |
| 1172 | 1174 | ||
| 1173 | fail_hotkey1: | 1175 | fail_hotkey1: |
| 1174 | |||
| 1175 | kfree(fujitsu_hotkey); | 1176 | kfree(fujitsu_hotkey); |
| 1176 | |||
| 1177 | fail_hotkey: | 1177 | fail_hotkey: |
| 1178 | |||
| 1179 | platform_driver_unregister(&fujitsupf_driver); | 1178 | platform_driver_unregister(&fujitsupf_driver); |
| 1180 | |||
| 1181 | fail_backlight: | 1179 | fail_backlight: |
| 1182 | |||
| 1183 | if (fujitsu->bl_device) | 1180 | if (fujitsu->bl_device) |
| 1184 | backlight_device_unregister(fujitsu->bl_device); | 1181 | backlight_device_unregister(fujitsu->bl_device); |
| 1185 | 1182 | fail_sysfs_group: | |
| 1183 | sysfs_remove_group(&fujitsu->pf_device->dev.kobj, | ||
| 1184 | &fujitsupf_attribute_group); | ||
| 1186 | fail_platform_device2: | 1185 | fail_platform_device2: |
| 1187 | |||
| 1188 | platform_device_del(fujitsu->pf_device); | 1186 | platform_device_del(fujitsu->pf_device); |
| 1189 | |||
| 1190 | fail_platform_device1: | 1187 | fail_platform_device1: |
| 1191 | |||
| 1192 | platform_device_put(fujitsu->pf_device); | 1188 | platform_device_put(fujitsu->pf_device); |
| 1193 | |||
| 1194 | fail_platform_driver: | 1189 | fail_platform_driver: |
| 1195 | |||
| 1196 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); | 1190 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); |
| 1197 | |||
| 1198 | fail_acpi: | 1191 | fail_acpi: |
| 1199 | |||
| 1200 | kfree(fujitsu); | 1192 | kfree(fujitsu); |
| 1201 | 1193 | ||
| 1202 | return ret; | 1194 | return ret; |
| @@ -1204,28 +1196,23 @@ fail_acpi: | |||
| 1204 | 1196 | ||
| 1205 | static void __exit fujitsu_cleanup(void) | 1197 | static void __exit fujitsu_cleanup(void) |
| 1206 | { | 1198 | { |
| 1207 | #ifdef CONFIG_LEDS_CLASS | 1199 | acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver); |
| 1208 | if (fujitsu_hotkey->logolamp_registered != 0) | ||
| 1209 | led_classdev_unregister(&logolamp_led); | ||
| 1210 | 1200 | ||
| 1211 | if (fujitsu_hotkey->kblamps_registered != 0) | 1201 | kfree(fujitsu_hotkey); |
| 1212 | led_classdev_unregister(&kblamps_led); | ||
| 1213 | #endif | ||
| 1214 | 1202 | ||
| 1215 | sysfs_remove_group(&fujitsu->pf_device->dev.kobj, | ||
| 1216 | &fujitsupf_attribute_group); | ||
| 1217 | platform_device_unregister(fujitsu->pf_device); | ||
| 1218 | platform_driver_unregister(&fujitsupf_driver); | 1203 | platform_driver_unregister(&fujitsupf_driver); |
| 1204 | |||
| 1219 | if (fujitsu->bl_device) | 1205 | if (fujitsu->bl_device) |
| 1220 | backlight_device_unregister(fujitsu->bl_device); | 1206 | backlight_device_unregister(fujitsu->bl_device); |
| 1221 | 1207 | ||
| 1222 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); | 1208 | sysfs_remove_group(&fujitsu->pf_device->dev.kobj, |
| 1209 | &fujitsupf_attribute_group); | ||
| 1223 | 1210 | ||
| 1224 | kfree(fujitsu); | 1211 | platform_device_unregister(fujitsu->pf_device); |
| 1225 | 1212 | ||
| 1226 | acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver); | 1213 | acpi_bus_unregister_driver(&acpi_fujitsu_driver); |
| 1227 | 1214 | ||
| 1228 | kfree(fujitsu_hotkey); | 1215 | kfree(fujitsu); |
| 1229 | 1216 | ||
| 1230 | printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n"); | 1217 | printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n"); |
| 1231 | } | 1218 | } |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index af04f5b049db..c2842171cec6 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -507,7 +507,7 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) | |||
| 507 | } | 507 | } |
| 508 | if (bluetooth_rfkill) { | 508 | if (bluetooth_rfkill) { |
| 509 | rfkill_unregister(bluetooth_rfkill); | 509 | rfkill_unregister(bluetooth_rfkill); |
| 510 | rfkill_destroy(wifi_rfkill); | 510 | rfkill_destroy(bluetooth_rfkill); |
| 511 | } | 511 | } |
| 512 | if (wwan_rfkill) { | 512 | if (wwan_rfkill) { |
| 513 | rfkill_unregister(wwan_rfkill); | 513 | rfkill_unregister(wwan_rfkill); |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index dafaa4a92df5..f9f68e0e7344 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
| @@ -976,15 +976,12 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, | |||
| 976 | void *context, void **return_value) | 976 | void *context, void **return_value) |
| 977 | { | 977 | { |
| 978 | struct acpi_device_info *info; | 978 | struct acpi_device_info *info; |
| 979 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
| 980 | |||
| 981 | if (ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) { | ||
| 982 | info = buffer.pointer; | ||
| 983 | 979 | ||
| 980 | if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { | ||
| 984 | printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", | 981 | printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", |
| 985 | (char *)&info->name, info->param_count); | 982 | (char *)&info->name, info->param_count); |
| 986 | 983 | ||
| 987 | kfree(buffer.pointer); | 984 | kfree(info); |
| 988 | } | 985 | } |
| 989 | 986 | ||
| 990 | return AE_OK; | 987 | return AE_OK; |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e85600852502..f78d27503925 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -1278,6 +1278,7 @@ static void tpacpi_destroy_rfkill(const enum tpacpi_rfk_id id) | |||
| 1278 | tp_rfk = tpacpi_rfkill_switches[id]; | 1278 | tp_rfk = tpacpi_rfkill_switches[id]; |
| 1279 | if (tp_rfk) { | 1279 | if (tp_rfk) { |
| 1280 | rfkill_unregister(tp_rfk->rfkill); | 1280 | rfkill_unregister(tp_rfk->rfkill); |
| 1281 | rfkill_destroy(tp_rfk->rfkill); | ||
| 1281 | tpacpi_rfkill_switches[id] = NULL; | 1282 | tpacpi_rfkill_switches[id] = NULL; |
| 1282 | kfree(tp_rfk); | 1283 | kfree(tp_rfk); |
| 1283 | } | 1284 | } |
| @@ -1601,6 +1602,196 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) | |||
| 1601 | #endif | 1602 | #endif |
| 1602 | } | 1603 | } |
| 1603 | 1604 | ||
| 1605 | /************************************************************************* | ||
| 1606 | * Firmware Data | ||
| 1607 | */ | ||
| 1608 | |||
| 1609 | /* | ||
| 1610 | * Table of recommended minimum BIOS versions | ||
| 1611 | * | ||
| 1612 | * Reasons for listing: | ||
| 1613 | * 1. Stable BIOS, listed because the unknown ammount of | ||
| 1614 | * bugs and bad ACPI behaviour on older versions | ||
| 1615 | * | ||
| 1616 | * 2. BIOS or EC fw with known bugs that trigger on Linux | ||
| 1617 | * | ||
| 1618 | * 3. BIOS with known reduced functionality in older versions | ||
| 1619 | * | ||
| 1620 | * We recommend the latest BIOS and EC version. | ||
| 1621 | * We only support the latest BIOS and EC fw version as a rule. | ||
| 1622 | * | ||
| 1623 | * Sources: IBM ThinkPad Public Web Documents (update changelogs), | ||
| 1624 | * Information from users in ThinkWiki | ||
| 1625 | * | ||
| 1626 | * WARNING: we use this table also to detect that the machine is | ||
| 1627 | * a ThinkPad in some cases, so don't remove entries lightly. | ||
| 1628 | */ | ||
| 1629 | |||
| 1630 | #define TPV_Q(__v, __id1, __id2, __bv1, __bv2) \ | ||
| 1631 | { .vendor = (__v), \ | ||
| 1632 | .bios = TPID(__id1, __id2), \ | ||
| 1633 | .ec = TPACPI_MATCH_ANY, \ | ||
| 1634 | .quirks = TPACPI_MATCH_ANY << 16 \ | ||
| 1635 | | (__bv1) << 8 | (__bv2) } | ||
| 1636 | |||
| 1637 | #define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \ | ||
| 1638 | __eid1, __eid2, __ev1, __ev2) \ | ||
| 1639 | { .vendor = (__v), \ | ||
| 1640 | .bios = TPID(__bid1, __bid2), \ | ||
| 1641 | .ec = TPID(__eid1, __eid2), \ | ||
| 1642 | .quirks = (__ev1) << 24 | (__ev2) << 16 \ | ||
| 1643 | | (__bv1) << 8 | (__bv2) } | ||
| 1644 | |||
| 1645 | #define TPV_QI0(__id1, __id2, __bv1, __bv2) \ | ||
| 1646 | TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2) | ||
| 1647 | |||
| 1648 | #define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ | ||
| 1649 | TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \ | ||
| 1650 | __bv1, __bv2, __id1, __id2, __ev1, __ev2) | ||
| 1651 | |||
| 1652 | #define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \ | ||
| 1653 | __eid1, __eid2, __ev1, __ev2) \ | ||
| 1654 | TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \ | ||
| 1655 | __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) | ||
| 1656 | |||
| 1657 | #define TPV_QL0(__id1, __id2, __bv1, __bv2) \ | ||
| 1658 | TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2) | ||
| 1659 | |||
| 1660 | #define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ | ||
| 1661 | TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \ | ||
| 1662 | __bv1, __bv2, __id1, __id2, __ev1, __ev2) | ||
| 1663 | |||
| 1664 | #define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \ | ||
| 1665 | __eid1, __eid2, __ev1, __ev2) \ | ||
| 1666 | TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \ | ||
| 1667 | __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) | ||
| 1668 | |||
| 1669 | static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = { | ||
| 1670 | /* Numeric models ------------------ */ | ||
| 1671 | /* FW MODEL BIOS VERS */ | ||
| 1672 | TPV_QI0('I', 'M', '6', '5'), /* 570 */ | ||
| 1673 | TPV_QI0('I', 'U', '2', '6'), /* 570E */ | ||
| 1674 | TPV_QI0('I', 'B', '5', '4'), /* 600 */ | ||
| 1675 | TPV_QI0('I', 'H', '4', '7'), /* 600E */ | ||
| 1676 | TPV_QI0('I', 'N', '3', '6'), /* 600E */ | ||
| 1677 | TPV_QI0('I', 'T', '5', '5'), /* 600X */ | ||
| 1678 | TPV_QI0('I', 'D', '4', '8'), /* 770, 770E, 770ED */ | ||
| 1679 | TPV_QI0('I', 'I', '4', '2'), /* 770X */ | ||
| 1680 | TPV_QI0('I', 'O', '2', '3'), /* 770Z */ | ||
| 1681 | |||
| 1682 | /* A-series ------------------------- */ | ||
| 1683 | /* FW MODEL BIOS VERS EC VERS */ | ||
| 1684 | TPV_QI0('I', 'W', '5', '9'), /* A20m */ | ||
| 1685 | TPV_QI0('I', 'V', '6', '9'), /* A20p */ | ||
| 1686 | TPV_QI0('1', '0', '2', '6'), /* A21e, A22e */ | ||
| 1687 | TPV_QI0('K', 'U', '3', '6'), /* A21e */ | ||
| 1688 | TPV_QI0('K', 'X', '3', '6'), /* A21m, A22m */ | ||
| 1689 | TPV_QI0('K', 'Y', '3', '8'), /* A21p, A22p */ | ||
| 1690 | TPV_QI0('1', 'B', '1', '7'), /* A22e */ | ||
| 1691 | TPV_QI0('1', '3', '2', '0'), /* A22m */ | ||
| 1692 | TPV_QI0('1', 'E', '7', '3'), /* A30/p (0) */ | ||
| 1693 | TPV_QI1('1', 'G', '4', '1', '1', '7'), /* A31/p (0) */ | ||
| 1694 | TPV_QI1('1', 'N', '1', '6', '0', '7'), /* A31/p (0) */ | ||
| 1695 | |||
| 1696 | /* G-series ------------------------- */ | ||
| 1697 | /* FW MODEL BIOS VERS */ | ||
| 1698 | TPV_QI0('1', 'T', 'A', '6'), /* G40 */ | ||
| 1699 | TPV_QI0('1', 'X', '5', '7'), /* G41 */ | ||
| 1700 | |||
| 1701 | /* R-series, T-series --------------- */ | ||
| 1702 | /* FW MODEL BIOS VERS EC VERS */ | ||
| 1703 | TPV_QI0('1', 'C', 'F', '0'), /* R30 */ | ||
| 1704 | TPV_QI0('1', 'F', 'F', '1'), /* R31 */ | ||
| 1705 | TPV_QI0('1', 'M', '9', '7'), /* R32 */ | ||
| 1706 | TPV_QI0('1', 'O', '6', '1'), /* R40 */ | ||
| 1707 | TPV_QI0('1', 'P', '6', '5'), /* R40 */ | ||
| 1708 | TPV_QI0('1', 'S', '7', '0'), /* R40e */ | ||
| 1709 | TPV_QI1('1', 'R', 'D', 'R', '7', '1'), /* R50/p, R51, | ||
| 1710 | T40/p, T41/p, T42/p (1) */ | ||
| 1711 | TPV_QI1('1', 'V', '7', '1', '2', '8'), /* R50e, R51 (1) */ | ||
| 1712 | TPV_QI1('7', '8', '7', '1', '0', '6'), /* R51e (1) */ | ||
| 1713 | TPV_QI1('7', '6', '6', '9', '1', '6'), /* R52 (1) */ | ||
| 1714 | TPV_QI1('7', '0', '6', '9', '2', '8'), /* R52, T43 (1) */ | ||
| 1715 | |||
| 1716 | TPV_QI0('I', 'Y', '6', '1'), /* T20 */ | ||
| 1717 | TPV_QI0('K', 'Z', '3', '4'), /* T21 */ | ||
| 1718 | TPV_QI0('1', '6', '3', '2'), /* T22 */ | ||
| 1719 | TPV_QI1('1', 'A', '6', '4', '2', '3'), /* T23 (0) */ | ||
| 1720 | TPV_QI1('1', 'I', '7', '1', '2', '0'), /* T30 (0) */ | ||
| 1721 | TPV_QI1('1', 'Y', '6', '5', '2', '9'), /* T43/p (1) */ | ||
| 1722 | |||
| 1723 | TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ | ||
| 1724 | TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ | ||
| 1725 | TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ | ||
| 1726 | |||
| 1727 | /* BIOS FW BIOS VERS EC FW EC VERS */ | ||
| 1728 | TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ | ||
| 1729 | TPV_QL2('7', 'I', '3', '4', '7', '9', '5', '0'), /* T60/p wide */ | ||
| 1730 | |||
| 1731 | /* X-series ------------------------- */ | ||
| 1732 | /* FW MODEL BIOS VERS EC VERS */ | ||
| 1733 | TPV_QI0('I', 'Z', '9', 'D'), /* X20, X21 */ | ||
| 1734 | TPV_QI0('1', 'D', '7', '0'), /* X22, X23, X24 */ | ||
| 1735 | TPV_QI1('1', 'K', '4', '8', '1', '8'), /* X30 (0) */ | ||
| 1736 | TPV_QI1('1', 'Q', '9', '7', '2', '3'), /* X31, X32 (0) */ | ||
| 1737 | TPV_QI1('1', 'U', 'D', '3', 'B', '2'), /* X40 (0) */ | ||
| 1738 | TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ | ||
| 1739 | TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ | ||
| 1740 | |||
| 1741 | TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ | ||
| 1742 | TPV_QL0('7', 'J', '3', '0'), /* X60t */ | ||
| 1743 | |||
| 1744 | /* (0) - older versions lack DMI EC fw string and functionality */ | ||
| 1745 | /* (1) - older versions known to lack functionality */ | ||
| 1746 | }; | ||
| 1747 | |||
| 1748 | #undef TPV_QL1 | ||
| 1749 | #undef TPV_QL0 | ||
| 1750 | #undef TPV_QI2 | ||
| 1751 | #undef TPV_QI1 | ||
| 1752 | #undef TPV_QI0 | ||
| 1753 | #undef TPV_Q_X | ||
| 1754 | #undef TPV_Q | ||
| 1755 | |||
| 1756 | static void __init tpacpi_check_outdated_fw(void) | ||
| 1757 | { | ||
| 1758 | unsigned long fwvers; | ||
| 1759 | u16 ec_version, bios_version; | ||
| 1760 | |||
| 1761 | fwvers = tpacpi_check_quirks(tpacpi_bios_version_qtable, | ||
| 1762 | ARRAY_SIZE(tpacpi_bios_version_qtable)); | ||
| 1763 | |||
| 1764 | if (!fwvers) | ||
| 1765 | return; | ||
| 1766 | |||
| 1767 | bios_version = fwvers & 0xffffU; | ||
| 1768 | ec_version = (fwvers >> 16) & 0xffffU; | ||
| 1769 | |||
| 1770 | /* note that unknown versions are set to 0x0000 and we use that */ | ||
| 1771 | if ((bios_version > thinkpad_id.bios_release) || | ||
| 1772 | (ec_version > thinkpad_id.ec_release && | ||
| 1773 | ec_version != TPACPI_MATCH_ANY)) { | ||
| 1774 | /* | ||
| 1775 | * The changelogs would let us track down the exact | ||
| 1776 | * reason, but it is just too much of a pain to track | ||
| 1777 | * it. We only list BIOSes that are either really | ||
| 1778 | * broken, or really stable to begin with, so it is | ||
| 1779 | * best if the user upgrades the firmware anyway. | ||
| 1780 | */ | ||
| 1781 | printk(TPACPI_WARN | ||
| 1782 | "WARNING: Outdated ThinkPad BIOS/EC firmware\n"); | ||
| 1783 | printk(TPACPI_WARN | ||
| 1784 | "WARNING: This firmware may be missing critical bug " | ||
| 1785 | "fixes and/or important features\n"); | ||
| 1786 | } | ||
| 1787 | } | ||
| 1788 | |||
| 1789 | static bool __init tpacpi_is_fw_known(void) | ||
| 1790 | { | ||
| 1791 | return tpacpi_check_quirks(tpacpi_bios_version_qtable, | ||
| 1792 | ARRAY_SIZE(tpacpi_bios_version_qtable)) != 0; | ||
| 1793 | } | ||
| 1794 | |||
| 1604 | /**************************************************************************** | 1795 | /**************************************************************************** |
| 1605 | **************************************************************************** | 1796 | **************************************************************************** |
| 1606 | * | 1797 | * |
| @@ -1634,6 +1825,7 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
| 1634 | (thinkpad_id.nummodel_str) ? | 1825 | (thinkpad_id.nummodel_str) ? |
| 1635 | thinkpad_id.nummodel_str : "unknown"); | 1826 | thinkpad_id.nummodel_str : "unknown"); |
| 1636 | 1827 | ||
| 1828 | tpacpi_check_outdated_fw(); | ||
| 1637 | return 0; | 1829 | return 0; |
| 1638 | } | 1830 | } |
| 1639 | 1831 | ||
| @@ -1731,16 +1923,42 @@ struct tp_nvram_state { | |||
| 1731 | u8 volume_level; | 1923 | u8 volume_level; |
| 1732 | }; | 1924 | }; |
| 1733 | 1925 | ||
| 1926 | /* kthread for the hotkey poller */ | ||
| 1734 | static struct task_struct *tpacpi_hotkey_task; | 1927 | static struct task_struct *tpacpi_hotkey_task; |
| 1735 | static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ | 1928 | |
| 1736 | static int hotkey_poll_freq = 10; /* Hz */ | 1929 | /* Acquired while the poller kthread is running, use to sync start/stop */ |
| 1737 | static struct mutex hotkey_thread_mutex; | 1930 | static struct mutex hotkey_thread_mutex; |
| 1931 | |||
| 1932 | /* | ||
| 1933 | * Acquire mutex to write poller control variables. | ||
| 1934 | * Increment hotkey_config_change when changing them. | ||
| 1935 | * | ||
| 1936 | * See HOTKEY_CONFIG_CRITICAL_START/HOTKEY_CONFIG_CRITICAL_END | ||
| 1937 | */ | ||
| 1738 | static struct mutex hotkey_thread_data_mutex; | 1938 | static struct mutex hotkey_thread_data_mutex; |
| 1739 | static unsigned int hotkey_config_change; | 1939 | static unsigned int hotkey_config_change; |
| 1740 | 1940 | ||
| 1941 | /* | ||
| 1942 | * hotkey poller control variables | ||
| 1943 | * | ||
| 1944 | * Must be atomic or readers will also need to acquire mutex | ||
| 1945 | */ | ||
| 1946 | static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ | ||
| 1947 | static unsigned int hotkey_poll_freq = 10; /* Hz */ | ||
| 1948 | |||
| 1949 | #define HOTKEY_CONFIG_CRITICAL_START \ | ||
| 1950 | do { \ | ||
| 1951 | mutex_lock(&hotkey_thread_data_mutex); \ | ||
| 1952 | hotkey_config_change++; \ | ||
| 1953 | } while (0); | ||
| 1954 | #define HOTKEY_CONFIG_CRITICAL_END \ | ||
| 1955 | mutex_unlock(&hotkey_thread_data_mutex); | ||
| 1956 | |||
| 1741 | #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ | 1957 | #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ |
| 1742 | 1958 | ||
| 1743 | #define hotkey_source_mask 0U | 1959 | #define hotkey_source_mask 0U |
| 1960 | #define HOTKEY_CONFIG_CRITICAL_START | ||
| 1961 | #define HOTKEY_CONFIG_CRITICAL_END | ||
| 1744 | 1962 | ||
| 1745 | #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ | 1963 | #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ |
| 1746 | 1964 | ||
| @@ -1765,19 +1983,6 @@ static u16 *hotkey_keycode_map; | |||
| 1765 | 1983 | ||
| 1766 | static struct attribute_set *hotkey_dev_attributes; | 1984 | static struct attribute_set *hotkey_dev_attributes; |
| 1767 | 1985 | ||
| 1768 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | ||
| 1769 | #define HOTKEY_CONFIG_CRITICAL_START \ | ||
| 1770 | do { \ | ||
| 1771 | mutex_lock(&hotkey_thread_data_mutex); \ | ||
| 1772 | hotkey_config_change++; \ | ||
| 1773 | } while (0); | ||
| 1774 | #define HOTKEY_CONFIG_CRITICAL_END \ | ||
| 1775 | mutex_unlock(&hotkey_thread_data_mutex); | ||
| 1776 | #else | ||
| 1777 | #define HOTKEY_CONFIG_CRITICAL_START | ||
| 1778 | #define HOTKEY_CONFIG_CRITICAL_END | ||
| 1779 | #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ | ||
| 1780 | |||
| 1781 | /* HKEY.MHKG() return bits */ | 1986 | /* HKEY.MHKG() return bits */ |
| 1782 | #define TP_HOTKEY_TABLET_MASK (1 << 3) | 1987 | #define TP_HOTKEY_TABLET_MASK (1 << 3) |
| 1783 | 1988 | ||
| @@ -1822,7 +2027,9 @@ static int hotkey_mask_get(void) | |||
| 1822 | if (!acpi_evalf(hkey_handle, &m, "DHKN", "d")) | 2027 | if (!acpi_evalf(hkey_handle, &m, "DHKN", "d")) |
| 1823 | return -EIO; | 2028 | return -EIO; |
| 1824 | } | 2029 | } |
| 2030 | HOTKEY_CONFIG_CRITICAL_START | ||
| 1825 | hotkey_mask = m | (hotkey_source_mask & hotkey_mask); | 2031 | hotkey_mask = m | (hotkey_source_mask & hotkey_mask); |
| 2032 | HOTKEY_CONFIG_CRITICAL_END | ||
| 1826 | 2033 | ||
| 1827 | return 0; | 2034 | return 0; |
| 1828 | } | 2035 | } |
| @@ -2075,6 +2282,7 @@ static int hotkey_kthread(void *data) | |||
| 2075 | unsigned int si, so; | 2282 | unsigned int si, so; |
| 2076 | unsigned long t; | 2283 | unsigned long t; |
| 2077 | unsigned int change_detector, must_reset; | 2284 | unsigned int change_detector, must_reset; |
| 2285 | unsigned int poll_freq; | ||
| 2078 | 2286 | ||
| 2079 | mutex_lock(&hotkey_thread_mutex); | 2287 | mutex_lock(&hotkey_thread_mutex); |
| 2080 | 2288 | ||
| @@ -2091,12 +2299,17 @@ static int hotkey_kthread(void *data) | |||
| 2091 | mutex_lock(&hotkey_thread_data_mutex); | 2299 | mutex_lock(&hotkey_thread_data_mutex); |
| 2092 | change_detector = hotkey_config_change; | 2300 | change_detector = hotkey_config_change; |
| 2093 | mask = hotkey_source_mask & hotkey_mask; | 2301 | mask = hotkey_source_mask & hotkey_mask; |
| 2302 | poll_freq = hotkey_poll_freq; | ||
| 2094 | mutex_unlock(&hotkey_thread_data_mutex); | 2303 | mutex_unlock(&hotkey_thread_data_mutex); |
| 2095 | hotkey_read_nvram(&s[so], mask); | 2304 | hotkey_read_nvram(&s[so], mask); |
| 2096 | 2305 | ||
| 2097 | while (!kthread_should_stop() && hotkey_poll_freq) { | 2306 | while (!kthread_should_stop()) { |
| 2098 | if (t == 0) | 2307 | if (t == 0) { |
| 2099 | t = 1000/hotkey_poll_freq; | 2308 | if (likely(poll_freq)) |
| 2309 | t = 1000/poll_freq; | ||
| 2310 | else | ||
| 2311 | t = 100; /* should never happen... */ | ||
| 2312 | } | ||
| 2100 | t = msleep_interruptible(t); | 2313 | t = msleep_interruptible(t); |
| 2101 | if (unlikely(kthread_should_stop())) | 2314 | if (unlikely(kthread_should_stop())) |
| 2102 | break; | 2315 | break; |
| @@ -2112,6 +2325,7 @@ static int hotkey_kthread(void *data) | |||
| 2112 | change_detector = hotkey_config_change; | 2325 | change_detector = hotkey_config_change; |
| 2113 | } | 2326 | } |
| 2114 | mask = hotkey_source_mask & hotkey_mask; | 2327 | mask = hotkey_source_mask & hotkey_mask; |
| 2328 | poll_freq = hotkey_poll_freq; | ||
| 2115 | mutex_unlock(&hotkey_thread_data_mutex); | 2329 | mutex_unlock(&hotkey_thread_data_mutex); |
| 2116 | 2330 | ||
| 2117 | if (likely(mask)) { | 2331 | if (likely(mask)) { |
| @@ -2131,6 +2345,7 @@ exit: | |||
| 2131 | return 0; | 2345 | return 0; |
| 2132 | } | 2346 | } |
| 2133 | 2347 | ||
| 2348 | /* call with hotkey_mutex held */ | ||
| 2134 | static void hotkey_poll_stop_sync(void) | 2349 | static void hotkey_poll_stop_sync(void) |
| 2135 | { | 2350 | { |
| 2136 | if (tpacpi_hotkey_task) { | 2351 | if (tpacpi_hotkey_task) { |
| @@ -2147,10 +2362,11 @@ static void hotkey_poll_stop_sync(void) | |||
| 2147 | } | 2362 | } |
| 2148 | 2363 | ||
| 2149 | /* call with hotkey_mutex held */ | 2364 | /* call with hotkey_mutex held */ |
| 2150 | static void hotkey_poll_setup(int may_warn) | 2365 | static void hotkey_poll_setup(bool may_warn) |
| 2151 | { | 2366 | { |
| 2152 | if ((hotkey_source_mask & hotkey_mask) != 0 && | 2367 | u32 hotkeys_to_poll = hotkey_source_mask & hotkey_mask; |
| 2153 | hotkey_poll_freq > 0 && | 2368 | |
| 2369 | if (hotkeys_to_poll != 0 && hotkey_poll_freq > 0 && | ||
| 2154 | (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { | 2370 | (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { |
| 2155 | if (!tpacpi_hotkey_task) { | 2371 | if (!tpacpi_hotkey_task) { |
| 2156 | tpacpi_hotkey_task = kthread_run(hotkey_kthread, | 2372 | tpacpi_hotkey_task = kthread_run(hotkey_kthread, |
| @@ -2164,26 +2380,37 @@ static void hotkey_poll_setup(int may_warn) | |||
| 2164 | } | 2380 | } |
| 2165 | } else { | 2381 | } else { |
| 2166 | hotkey_poll_stop_sync(); | 2382 | hotkey_poll_stop_sync(); |
| 2167 | if (may_warn && | 2383 | if (may_warn && hotkeys_to_poll != 0 && |
| 2168 | hotkey_source_mask != 0 && hotkey_poll_freq == 0) { | 2384 | hotkey_poll_freq == 0) { |
| 2169 | printk(TPACPI_NOTICE | 2385 | printk(TPACPI_NOTICE |
| 2170 | "hot keys 0x%08x require polling, " | 2386 | "hot keys 0x%08x require polling, " |
| 2171 | "which is currently disabled\n", | 2387 | "which is currently disabled\n", |
| 2172 | hotkey_source_mask); | 2388 | hotkeys_to_poll); |
| 2173 | } | 2389 | } |
| 2174 | } | 2390 | } |
| 2175 | } | 2391 | } |
| 2176 | 2392 | ||
| 2177 | static void hotkey_poll_setup_safe(int may_warn) | 2393 | static void hotkey_poll_setup_safe(bool may_warn) |
| 2178 | { | 2394 | { |
| 2179 | mutex_lock(&hotkey_mutex); | 2395 | mutex_lock(&hotkey_mutex); |
| 2180 | hotkey_poll_setup(may_warn); | 2396 | hotkey_poll_setup(may_warn); |
| 2181 | mutex_unlock(&hotkey_mutex); | 2397 | mutex_unlock(&hotkey_mutex); |
| 2182 | } | 2398 | } |
| 2183 | 2399 | ||
| 2400 | /* call with hotkey_mutex held */ | ||
| 2401 | static void hotkey_poll_set_freq(unsigned int freq) | ||
| 2402 | { | ||
| 2403 | if (!freq) | ||
| 2404 | hotkey_poll_stop_sync(); | ||
| 2405 | |||
| 2406 | HOTKEY_CONFIG_CRITICAL_START | ||
| 2407 | hotkey_poll_freq = freq; | ||
| 2408 | HOTKEY_CONFIG_CRITICAL_END | ||
| 2409 | } | ||
| 2410 | |||
| 2184 | #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ | 2411 | #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ |
| 2185 | 2412 | ||
| 2186 | static void hotkey_poll_setup_safe(int __unused) | 2413 | static void hotkey_poll_setup_safe(bool __unused) |
| 2187 | { | 2414 | { |
| 2188 | } | 2415 | } |
| 2189 | 2416 | ||
| @@ -2201,7 +2428,7 @@ static int hotkey_inputdev_open(struct input_dev *dev) | |||
| 2201 | case TPACPI_LIFE_EXITING: | 2428 | case TPACPI_LIFE_EXITING: |
| 2202 | return -EBUSY; | 2429 | return -EBUSY; |
| 2203 | case TPACPI_LIFE_RUNNING: | 2430 | case TPACPI_LIFE_RUNNING: |
| 2204 | hotkey_poll_setup_safe(0); | 2431 | hotkey_poll_setup_safe(false); |
| 2205 | return 0; | 2432 | return 0; |
| 2206 | } | 2433 | } |
| 2207 | 2434 | ||
| @@ -2214,7 +2441,7 @@ static void hotkey_inputdev_close(struct input_dev *dev) | |||
| 2214 | { | 2441 | { |
| 2215 | /* disable hotkey polling when possible */ | 2442 | /* disable hotkey polling when possible */ |
| 2216 | if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) | 2443 | if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) |
| 2217 | hotkey_poll_setup_safe(0); | 2444 | hotkey_poll_setup_safe(false); |
| 2218 | } | 2445 | } |
| 2219 | 2446 | ||
| 2220 | /* sysfs hotkey enable ------------------------------------------------- */ | 2447 | /* sysfs hotkey enable ------------------------------------------------- */ |
| @@ -2288,7 +2515,7 @@ static ssize_t hotkey_mask_store(struct device *dev, | |||
| 2288 | res = hotkey_mask_set(t); | 2515 | res = hotkey_mask_set(t); |
| 2289 | 2516 | ||
| 2290 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | 2517 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL |
| 2291 | hotkey_poll_setup(1); | 2518 | hotkey_poll_setup(true); |
| 2292 | #endif | 2519 | #endif |
| 2293 | 2520 | ||
| 2294 | mutex_unlock(&hotkey_mutex); | 2521 | mutex_unlock(&hotkey_mutex); |
| @@ -2318,6 +2545,8 @@ static ssize_t hotkey_bios_mask_show(struct device *dev, | |||
| 2318 | struct device_attribute *attr, | 2545 | struct device_attribute *attr, |
| 2319 | char *buf) | 2546 | char *buf) |
| 2320 | { | 2547 | { |
| 2548 | printk_deprecated_attribute("hotkey_bios_mask", | ||
| 2549 | "This attribute is useless."); | ||
| 2321 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); | 2550 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); |
| 2322 | } | 2551 | } |
| 2323 | 2552 | ||
| @@ -2377,7 +2606,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev, | |||
| 2377 | hotkey_source_mask = t; | 2606 | hotkey_source_mask = t; |
| 2378 | HOTKEY_CONFIG_CRITICAL_END | 2607 | HOTKEY_CONFIG_CRITICAL_END |
| 2379 | 2608 | ||
| 2380 | hotkey_poll_setup(1); | 2609 | hotkey_poll_setup(true); |
| 2610 | hotkey_mask_set(hotkey_mask); | ||
| 2381 | 2611 | ||
| 2382 | mutex_unlock(&hotkey_mutex); | 2612 | mutex_unlock(&hotkey_mutex); |
| 2383 | 2613 | ||
| @@ -2410,9 +2640,9 @@ static ssize_t hotkey_poll_freq_store(struct device *dev, | |||
| 2410 | if (mutex_lock_killable(&hotkey_mutex)) | 2640 | if (mutex_lock_killable(&hotkey_mutex)) |
| 2411 | return -ERESTARTSYS; | 2641 | return -ERESTARTSYS; |
| 2412 | 2642 | ||
| 2413 | hotkey_poll_freq = t; | 2643 | hotkey_poll_set_freq(t); |
| 2644 | hotkey_poll_setup(true); | ||
| 2414 | 2645 | ||
| 2415 | hotkey_poll_setup(1); | ||
| 2416 | mutex_unlock(&hotkey_mutex); | 2646 | mutex_unlock(&hotkey_mutex); |
| 2417 | 2647 | ||
| 2418 | tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); | 2648 | tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); |
| @@ -2603,7 +2833,9 @@ static void tpacpi_send_radiosw_update(void) | |||
| 2603 | static void hotkey_exit(void) | 2833 | static void hotkey_exit(void) |
| 2604 | { | 2834 | { |
| 2605 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | 2835 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL |
| 2836 | mutex_lock(&hotkey_mutex); | ||
| 2606 | hotkey_poll_stop_sync(); | 2837 | hotkey_poll_stop_sync(); |
| 2838 | mutex_unlock(&hotkey_mutex); | ||
| 2607 | #endif | 2839 | #endif |
| 2608 | 2840 | ||
| 2609 | if (hotkey_dev_attributes) | 2841 | if (hotkey_dev_attributes) |
| @@ -2623,6 +2855,15 @@ static void hotkey_exit(void) | |||
| 2623 | } | 2855 | } |
| 2624 | } | 2856 | } |
| 2625 | 2857 | ||
| 2858 | static void __init hotkey_unmap(const unsigned int scancode) | ||
| 2859 | { | ||
| 2860 | if (hotkey_keycode_map[scancode] != KEY_RESERVED) { | ||
| 2861 | clear_bit(hotkey_keycode_map[scancode], | ||
| 2862 | tpacpi_inputdev->keybit); | ||
| 2863 | hotkey_keycode_map[scancode] = KEY_RESERVED; | ||
| 2864 | } | ||
| 2865 | } | ||
| 2866 | |||
| 2626 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 2867 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
| 2627 | { | 2868 | { |
| 2628 | /* Requirements for changing the default keymaps: | 2869 | /* Requirements for changing the default keymaps: |
| @@ -2701,11 +2942,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2701 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | 2942 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ |
| 2702 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | 2943 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ |
| 2703 | 2944 | ||
| 2704 | /* These either have to go through ACPI video, or | 2945 | /* These should be enabled --only-- when ACPI video |
| 2705 | * act like in the IBM ThinkPads, so don't ever | 2946 | * is disabled (i.e. in "vendor" mode), and are handled |
| 2706 | * enable them by default */ | 2947 | * in a special way by the init code */ |
| 2707 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ | 2948 | KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ |
| 2708 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ | 2949 | KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ |
| 2709 | 2950 | ||
| 2710 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | 2951 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ |
| 2711 | 2952 | ||
| @@ -2831,19 +3072,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2831 | goto err_exit; | 3072 | goto err_exit; |
| 2832 | } | 3073 | } |
| 2833 | 3074 | ||
| 2834 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | ||
| 2835 | if (tp_features.hotkey_mask) { | ||
| 2836 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK | ||
| 2837 | & ~hotkey_all_mask; | ||
| 2838 | } else { | ||
| 2839 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; | ||
| 2840 | } | ||
| 2841 | |||
| 2842 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | ||
| 2843 | "hotkey source mask 0x%08x, polling freq %d\n", | ||
| 2844 | hotkey_source_mask, hotkey_poll_freq); | ||
| 2845 | #endif | ||
| 2846 | |||
| 2847 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES | 3075 | #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES |
| 2848 | if (dbg_wlswemul) { | 3076 | if (dbg_wlswemul) { |
| 2849 | tp_features.hotkey_wlsw = 1; | 3077 | tp_features.hotkey_wlsw = 1; |
| @@ -2944,17 +3172,31 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2944 | "Disabling thinkpad-acpi brightness events " | 3172 | "Disabling thinkpad-acpi brightness events " |
| 2945 | "by default...\n"); | 3173 | "by default...\n"); |
| 2946 | 3174 | ||
| 2947 | /* The hotkey_reserved_mask change below is not | 3175 | /* Disable brightness up/down on Lenovo thinkpads when |
| 2948 | * necessary while the keys are at KEY_RESERVED in the | 3176 | * ACPI is handling them, otherwise it is plain impossible |
| 2949 | * default map, but better safe than sorry, leave it | 3177 | * for userspace to do something even remotely sane */ |
| 2950 | * here as a marker of what we have to do, especially | ||
| 2951 | * when we finally become able to set this at runtime | ||
| 2952 | * on response to X.org requests */ | ||
| 2953 | hotkey_reserved_mask |= | 3178 | hotkey_reserved_mask |= |
| 2954 | (1 << TP_ACPI_HOTKEYSCAN_FNHOME) | 3179 | (1 << TP_ACPI_HOTKEYSCAN_FNHOME) |
| 2955 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); | 3180 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); |
| 3181 | hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNHOME); | ||
| 3182 | hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNEND); | ||
| 2956 | } | 3183 | } |
| 2957 | 3184 | ||
| 3185 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | ||
| 3186 | if (tp_features.hotkey_mask) { | ||
| 3187 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK | ||
| 3188 | & ~hotkey_all_mask | ||
| 3189 | & ~hotkey_reserved_mask; | ||
| 3190 | } else { | ||
| 3191 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK | ||
| 3192 | & ~hotkey_reserved_mask; | ||
| 3193 | } | ||
| 3194 | |||
| 3195 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | ||
| 3196 | "hotkey source mask 0x%08x, polling freq %u\n", | ||
| 3197 | hotkey_source_mask, hotkey_poll_freq); | ||
| 3198 | #endif | ||
| 3199 | |||
| 2958 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | 3200 | dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
| 2959 | "enabling firmware HKEY event interface...\n"); | 3201 | "enabling firmware HKEY event interface...\n"); |
| 2960 | res = hotkey_status_set(true); | 3202 | res = hotkey_status_set(true); |
| @@ -2978,7 +3220,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2978 | tpacpi_inputdev->open = &hotkey_inputdev_open; | 3220 | tpacpi_inputdev->open = &hotkey_inputdev_open; |
| 2979 | tpacpi_inputdev->close = &hotkey_inputdev_close; | 3221 | tpacpi_inputdev->close = &hotkey_inputdev_close; |
| 2980 | 3222 | ||
| 2981 | hotkey_poll_setup_safe(1); | 3223 | hotkey_poll_setup_safe(true); |
| 2982 | tpacpi_send_radiosw_update(); | 3224 | tpacpi_send_radiosw_update(); |
| 2983 | tpacpi_input_send_tabletsw(); | 3225 | tpacpi_input_send_tabletsw(); |
| 2984 | 3226 | ||
| @@ -3266,7 +3508,7 @@ static void hotkey_resume(void) | |||
| 3266 | hotkey_tablet_mode_notify_change(); | 3508 | hotkey_tablet_mode_notify_change(); |
| 3267 | hotkey_wakeup_reason_notify_change(); | 3509 | hotkey_wakeup_reason_notify_change(); |
| 3268 | hotkey_wakeup_hotunplug_complete_notify_change(); | 3510 | hotkey_wakeup_hotunplug_complete_notify_change(); |
| 3269 | hotkey_poll_setup_safe(0); | 3511 | hotkey_poll_setup_safe(false); |
| 3270 | } | 3512 | } |
| 3271 | 3513 | ||
| 3272 | /* procfs -------------------------------------------------------------- */ | 3514 | /* procfs -------------------------------------------------------------- */ |
| @@ -3338,7 +3580,8 @@ static int hotkey_write(char *buf) | |||
| 3338 | hotkey_enabledisable_warn(0); | 3580 | hotkey_enabledisable_warn(0); |
| 3339 | res = -EPERM; | 3581 | res = -EPERM; |
| 3340 | } else if (strlencmp(cmd, "reset") == 0) { | 3582 | } else if (strlencmp(cmd, "reset") == 0) { |
| 3341 | mask = hotkey_orig_mask; | 3583 | mask = (hotkey_all_mask | hotkey_source_mask) |
| 3584 | & ~hotkey_reserved_mask; | ||
| 3342 | } else if (sscanf(cmd, "0x%x", &mask) == 1) { | 3585 | } else if (sscanf(cmd, "0x%x", &mask) == 1) { |
| 3343 | /* mask set */ | 3586 | /* mask set */ |
| 3344 | } else if (sscanf(cmd, "%x", &mask) == 1) { | 3587 | } else if (sscanf(cmd, "%x", &mask) == 1) { |
| @@ -5655,16 +5898,16 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { | |||
| 5655 | /* Models with ATI GPUs known to require ECNVRAM mode */ | 5898 | /* Models with ATI GPUs known to require ECNVRAM mode */ |
| 5656 | TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ | 5899 | TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ |
| 5657 | 5900 | ||
| 5658 | /* Models with ATI GPUs (waiting confirmation) */ | 5901 | /* Models with ATI GPUs that can use ECNVRAM */ |
| 5659 | TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | 5902 | TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), |
| 5660 | TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | 5903 | TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), |
| 5661 | TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | 5904 | TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), |
| 5662 | TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | 5905 | TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), |
| 5663 | 5906 | ||
| 5664 | /* Models with Intel Extreme Graphics 2 (waiting confirmation) */ | 5907 | /* Models with Intel Extreme Graphics 2 */ |
| 5908 | TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), | ||
| 5665 | TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | 5909 | TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), |
| 5666 | TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | 5910 | TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), |
| 5667 | TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
| 5668 | 5911 | ||
| 5669 | /* Models with Intel GMA900 */ | 5912 | /* Models with Intel GMA900 */ |
| 5670 | TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ | 5913 | TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ |
| @@ -7524,9 +7767,11 @@ static int __init probe_for_thinkpad(void) | |||
| 7524 | 7767 | ||
| 7525 | /* | 7768 | /* |
| 7526 | * Non-ancient models have better DMI tagging, but very old models | 7769 | * Non-ancient models have better DMI tagging, but very old models |
| 7527 | * don't. | 7770 | * don't. tpacpi_is_fw_known() is a cheat to help in that case. |
| 7528 | */ | 7771 | */ |
| 7529 | is_thinkpad = (thinkpad_id.model_str != NULL); | 7772 | is_thinkpad = (thinkpad_id.model_str != NULL) || |
| 7773 | (thinkpad_id.ec_model != 0) || | ||
| 7774 | tpacpi_is_fw_known(); | ||
| 7530 | 7775 | ||
| 7531 | /* ec is required because many other handles are relative to it */ | 7776 | /* ec is required because many other handles are relative to it */ |
| 7532 | TPACPI_ACPIHANDLE_INIT(ec); | 7777 | TPACPI_ACPIHANDLE_INIT(ec); |
| @@ -7537,13 +7782,6 @@ static int __init probe_for_thinkpad(void) | |||
| 7537 | return -ENODEV; | 7782 | return -ENODEV; |
| 7538 | } | 7783 | } |
| 7539 | 7784 | ||
| 7540 | /* | ||
| 7541 | * Risks a regression on very old machines, but reduces potential | ||
| 7542 | * false positives a damn great deal | ||
| 7543 | */ | ||
| 7544 | if (!is_thinkpad) | ||
| 7545 | is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); | ||
| 7546 | |||
| 7547 | if (!is_thinkpad && !force_load) | 7785 | if (!is_thinkpad && !force_load) |
| 7548 | return -ENODEV; | 7786 | return -ENODEV; |
| 7549 | 7787 | ||
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c new file mode 100644 index 000000000000..02f3d4e9e666 --- /dev/null +++ b/drivers/platform/x86/topstar-laptop.c | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | /* | ||
| 2 | * ACPI driver for Topstar notebooks (hotkeys support only) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Herton Ronaldo Krzesinski <herton@mandriva.com.br> | ||
| 5 | * | ||
| 6 | * Implementation inspired by existing x86 platform drivers, in special | ||
| 7 | * asus/eepc/fujitsu-laptop, thanks to their authors | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/acpi.h> | ||
| 20 | #include <linux/input.h> | ||
| 21 | |||
| 22 | #define ACPI_TOPSTAR_CLASS "topstar" | ||
| 23 | |||
| 24 | struct topstar_hkey { | ||
| 25 | struct input_dev *inputdev; | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct tps_key_entry { | ||
| 29 | u8 code; | ||
| 30 | u16 keycode; | ||
| 31 | }; | ||
| 32 | |||
| 33 | static struct tps_key_entry topstar_keymap[] = { | ||
| 34 | { 0x80, KEY_BRIGHTNESSUP }, | ||
| 35 | { 0x81, KEY_BRIGHTNESSDOWN }, | ||
| 36 | { 0x83, KEY_VOLUMEUP }, | ||
| 37 | { 0x84, KEY_VOLUMEDOWN }, | ||
| 38 | { 0x85, KEY_MUTE }, | ||
| 39 | { 0x86, KEY_SWITCHVIDEOMODE }, | ||
| 40 | { 0x87, KEY_F13 }, /* touchpad enable/disable key */ | ||
| 41 | { 0x88, KEY_WLAN }, | ||
| 42 | { 0x8a, KEY_WWW }, | ||
| 43 | { 0x8b, KEY_MAIL }, | ||
| 44 | { 0x8c, KEY_MEDIA }, | ||
| 45 | { 0x96, KEY_F14 }, /* G key? */ | ||
| 46 | { } | ||
| 47 | }; | ||
| 48 | |||
| 49 | static struct tps_key_entry *tps_get_key_by_scancode(int code) | ||
| 50 | { | ||
| 51 | struct tps_key_entry *key; | ||
| 52 | |||
| 53 | for (key = topstar_keymap; key->code; key++) | ||
| 54 | if (code == key->code) | ||
| 55 | return key; | ||
| 56 | |||
| 57 | return NULL; | ||
| 58 | } | ||
| 59 | |||
| 60 | static struct tps_key_entry *tps_get_key_by_keycode(int code) | ||
| 61 | { | ||
| 62 | struct tps_key_entry *key; | ||
| 63 | |||
| 64 | for (key = topstar_keymap; key->code; key++) | ||
| 65 | if (code == key->keycode) | ||
| 66 | return key; | ||
| 67 | |||
| 68 | return NULL; | ||
| 69 | } | ||
| 70 | |||
| 71 | static void acpi_topstar_notify(struct acpi_device *device, u32 event) | ||
| 72 | { | ||
| 73 | struct tps_key_entry *key; | ||
| 74 | static bool dup_evnt[2]; | ||
| 75 | bool *dup; | ||
| 76 | struct topstar_hkey *hkey = acpi_driver_data(device); | ||
| 77 | |||
| 78 | /* 0x83 and 0x84 key events comes duplicated... */ | ||
| 79 | if (event == 0x83 || event == 0x84) { | ||
| 80 | dup = &dup_evnt[event - 0x83]; | ||
| 81 | if (*dup) { | ||
| 82 | *dup = false; | ||
| 83 | return; | ||
| 84 | } | ||
| 85 | *dup = true; | ||
| 86 | } | ||
| 87 | |||
| 88 | /* | ||
| 89 | * 'G key' generate two event codes, convert to only | ||
| 90 | * one event/key code for now (3G switch?) | ||
| 91 | */ | ||
| 92 | if (event == 0x97) | ||
| 93 | event = 0x96; | ||
| 94 | |||
| 95 | key = tps_get_key_by_scancode(event); | ||
| 96 | if (key) { | ||
| 97 | input_report_key(hkey->inputdev, key->keycode, 1); | ||
| 98 | input_sync(hkey->inputdev); | ||
| 99 | input_report_key(hkey->inputdev, key->keycode, 0); | ||
| 100 | input_sync(hkey->inputdev); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* Known non hotkey events don't handled or that we don't care yet */ | ||
| 105 | if (event == 0x8e || event == 0x8f || event == 0x90) | ||
| 106 | return; | ||
| 107 | |||
| 108 | pr_info("unknown event = 0x%02x\n", event); | ||
| 109 | } | ||
| 110 | |||
| 111 | static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) | ||
| 112 | { | ||
| 113 | acpi_status status; | ||
| 114 | union acpi_object fncx_params[1] = { | ||
| 115 | { .type = ACPI_TYPE_INTEGER } | ||
| 116 | }; | ||
| 117 | struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] }; | ||
| 118 | |||
| 119 | fncx_params[0].integer.value = state ? 0x86 : 0x87; | ||
| 120 | status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL); | ||
| 121 | if (ACPI_FAILURE(status)) { | ||
| 122 | pr_err("Unable to switch FNCX notifications\n"); | ||
| 123 | return -ENODEV; | ||
| 124 | } | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
| 130 | { | ||
| 131 | struct tps_key_entry *key = tps_get_key_by_scancode(scancode); | ||
| 132 | |||
| 133 | if (!key) | ||
| 134 | return -EINVAL; | ||
| 135 | |||
| 136 | *keycode = key->keycode; | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
| 141 | { | ||
| 142 | struct tps_key_entry *key; | ||
| 143 | int old_keycode; | ||
| 144 | |||
| 145 | if (keycode < 0 || keycode > KEY_MAX) | ||
| 146 | return -EINVAL; | ||
| 147 | |||
| 148 | key = tps_get_key_by_scancode(scancode); | ||
| 149 | |||
| 150 | if (!key) | ||
| 151 | return -EINVAL; | ||
| 152 | |||
| 153 | old_keycode = key->keycode; | ||
| 154 | key->keycode = keycode; | ||
| 155 | set_bit(keycode, dev->keybit); | ||
| 156 | if (!tps_get_key_by_keycode(old_keycode)) | ||
| 157 | clear_bit(old_keycode, dev->keybit); | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) | ||
| 162 | { | ||
| 163 | struct tps_key_entry *key; | ||
| 164 | |||
| 165 | hkey->inputdev = input_allocate_device(); | ||
| 166 | if (!hkey->inputdev) { | ||
| 167 | pr_err("Unable to allocate input device\n"); | ||
| 168 | return -ENODEV; | ||
| 169 | } | ||
| 170 | hkey->inputdev->name = "Topstar Laptop extra buttons"; | ||
| 171 | hkey->inputdev->phys = "topstar/input0"; | ||
| 172 | hkey->inputdev->id.bustype = BUS_HOST; | ||
| 173 | hkey->inputdev->getkeycode = topstar_getkeycode; | ||
| 174 | hkey->inputdev->setkeycode = topstar_setkeycode; | ||
| 175 | for (key = topstar_keymap; key->code; key++) { | ||
| 176 | set_bit(EV_KEY, hkey->inputdev->evbit); | ||
| 177 | set_bit(key->keycode, hkey->inputdev->keybit); | ||
| 178 | } | ||
| 179 | if (input_register_device(hkey->inputdev)) { | ||
| 180 | pr_err("Unable to register input device\n"); | ||
| 181 | input_free_device(hkey->inputdev); | ||
| 182 | return -ENODEV; | ||
| 183 | } | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int acpi_topstar_add(struct acpi_device *device) | ||
| 189 | { | ||
| 190 | struct topstar_hkey *tps_hkey; | ||
| 191 | |||
| 192 | tps_hkey = kzalloc(sizeof(struct topstar_hkey), GFP_KERNEL); | ||
| 193 | if (!tps_hkey) | ||
| 194 | return -ENOMEM; | ||
| 195 | |||
| 196 | strcpy(acpi_device_name(device), "Topstar TPSACPI"); | ||
| 197 | strcpy(acpi_device_class(device), ACPI_TOPSTAR_CLASS); | ||
| 198 | |||
| 199 | if (acpi_topstar_fncx_switch(device, true)) | ||
| 200 | goto add_err; | ||
| 201 | |||
| 202 | if (acpi_topstar_init_hkey(tps_hkey)) | ||
| 203 | goto add_err; | ||
| 204 | |||
| 205 | device->driver_data = tps_hkey; | ||
| 206 | return 0; | ||
| 207 | |||
| 208 | add_err: | ||
| 209 | kfree(tps_hkey); | ||
| 210 | return -ENODEV; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int acpi_topstar_remove(struct acpi_device *device, int type) | ||
| 214 | { | ||
| 215 | struct topstar_hkey *tps_hkey = acpi_driver_data(device); | ||
| 216 | |||
| 217 | acpi_topstar_fncx_switch(device, false); | ||
| 218 | |||
| 219 | input_unregister_device(tps_hkey->inputdev); | ||
| 220 | kfree(tps_hkey); | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static const struct acpi_device_id topstar_device_ids[] = { | ||
| 226 | { "TPSACPI01", 0 }, | ||
| 227 | { "", 0 }, | ||
| 228 | }; | ||
| 229 | MODULE_DEVICE_TABLE(acpi, topstar_device_ids); | ||
| 230 | |||
| 231 | static struct acpi_driver acpi_topstar_driver = { | ||
| 232 | .name = "Topstar laptop ACPI driver", | ||
| 233 | .class = ACPI_TOPSTAR_CLASS, | ||
| 234 | .ids = topstar_device_ids, | ||
| 235 | .ops = { | ||
| 236 | .add = acpi_topstar_add, | ||
| 237 | .remove = acpi_topstar_remove, | ||
| 238 | .notify = acpi_topstar_notify, | ||
| 239 | }, | ||
| 240 | }; | ||
| 241 | |||
| 242 | static int __init topstar_laptop_init(void) | ||
| 243 | { | ||
| 244 | int ret; | ||
| 245 | |||
| 246 | ret = acpi_bus_register_driver(&acpi_topstar_driver); | ||
| 247 | if (ret < 0) | ||
| 248 | return ret; | ||
| 249 | |||
| 250 | printk(KERN_INFO "Topstar Laptop ACPI extras driver loaded\n"); | ||
| 251 | |||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | static void __exit topstar_laptop_exit(void) | ||
| 256 | { | ||
| 257 | acpi_bus_unregister_driver(&acpi_topstar_driver); | ||
| 258 | } | ||
| 259 | |||
| 260 | module_init(topstar_laptop_init); | ||
| 261 | module_exit(topstar_laptop_exit); | ||
| 262 | |||
| 263 | MODULE_AUTHOR("Herton Ronaldo Krzesinski"); | ||
| 264 | MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); | ||
| 265 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index f215a5919192..177f8d767df4 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c | |||
| @@ -42,7 +42,6 @@ MODULE_LICENSE("GPL"); | |||
| 42 | 42 | ||
| 43 | #define ACPI_WMI_CLASS "wmi" | 43 | #define ACPI_WMI_CLASS "wmi" |
| 44 | 44 | ||
| 45 | #undef PREFIX | ||
| 46 | #define PREFIX "ACPI: WMI: " | 45 | #define PREFIX "ACPI: WMI: " |
| 47 | 46 | ||
| 48 | static DEFINE_MUTEX(wmi_data_lock); | 47 | static DEFINE_MUTEX(wmi_data_lock); |
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 9496494f340e..c07fdb94d665 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
| @@ -194,13 +194,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
| 194 | pnpacpi_parse_resource_option_data(dev); | 194 | pnpacpi_parse_resource_option_data(dev); |
| 195 | 195 | ||
| 196 | if (device->flags.compatible_ids) { | 196 | if (device->flags.compatible_ids) { |
| 197 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; | 197 | struct acpica_device_id_list *cid_list = device->pnp.cid_list; |
| 198 | int i; | 198 | int i; |
| 199 | 199 | ||
| 200 | for (i = 0; i < cid_list->count; i++) { | 200 | for (i = 0; i < cid_list->count; i++) { |
| 201 | if (!ispnpidacpi(cid_list->id[i].value)) | 201 | if (!ispnpidacpi(cid_list->ids[i].string)) |
| 202 | continue; | 202 | continue; |
| 203 | pnp_add_id(dev, cid_list->id[i].value); | 203 | pnp_add_id(dev, cid_list->ids[i].string); |
| 204 | } | 204 | } |
| 205 | } | 205 | } |
| 206 | 206 | ||
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index a86e952ed4ca..bf7c687519ef 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
| @@ -15,6 +15,7 @@ menuconfig THERMAL | |||
| 15 | 15 | ||
| 16 | config THERMAL_HWMON | 16 | config THERMAL_HWMON |
| 17 | bool "Hardware monitoring support" | 17 | bool "Hardware monitoring support" |
| 18 | depends on THERMAL | ||
| 18 | depends on HWMON=y || HWMON=THERMAL | 19 | depends on HWMON=y || HWMON=THERMAL |
| 19 | help | 20 | help |
| 20 | The generic thermal sysfs driver's hardware monitoring support | 21 | The generic thermal sysfs driver's hardware monitoring support |
