diff options
51 files changed, 2073 insertions, 737 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-firmware_node b/Documentation/ABI/testing/sysfs-devices-firmware_node new file mode 100644 index 000000000000..46badc9ea284 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-firmware_node | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | What: /sys/devices/.../firmware_node/ | ||
| 2 | Date: September 2012 | ||
| 3 | Contact: <> | ||
| 4 | Description: | ||
| 5 | The /sys/devices/.../firmware_node directory contains attributes | ||
| 6 | allowing the user space to check and modify some firmware | ||
| 7 | related properties of given device. | ||
| 8 | |||
| 9 | What: /sys/devices/.../firmware_node/description | ||
| 10 | Date: September 2012 | ||
| 11 | Contact: Lance Ortiz <lance.ortiz@hp.com> | ||
| 12 | Description: | ||
| 13 | The /sys/devices/.../firmware/description attribute contains a string | ||
| 14 | that describes the device as provided by the _STR method in the ACPI | ||
| 15 | namespace. This attribute is read-only. If the device does not have | ||
| 16 | an _STR method associated with it in the ACPI namespace, this | ||
| 17 | attribute is not present. | ||
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 0a1b3435f920..7f1d40797e80 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile | |||
| @@ -158,5 +158,6 @@ acpi-y += \ | |||
| 158 | utresrc.o \ | 158 | utresrc.o \ |
| 159 | utstate.o \ | 159 | utstate.o \ |
| 160 | utxface.o \ | 160 | utxface.o \ |
| 161 | utxfinit.o \ | ||
| 161 | utxferror.o \ | 162 | utxferror.o \ |
| 162 | utxfmutex.o | 163 | utxfmutex.o |
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 5de4ec72766d..d902d31abc6c 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h | |||
| @@ -110,8 +110,7 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); | |||
| 110 | /* | 110 | /* |
| 111 | * hwgpe - GPE support | 111 | * hwgpe - GPE support |
| 112 | */ | 112 | */ |
| 113 | u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, | 113 | u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info); |
| 114 | struct acpi_gpe_register_info *gpe_register_info); | ||
| 115 | 114 | ||
| 116 | acpi_status | 115 | acpi_status |
| 117 | acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action); | 116 | acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action); |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index cc80fe10e8ea..c816ee675094 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
| @@ -707,15 +707,18 @@ union acpi_parse_value { | |||
| 707 | u8 disasm_opcode; /* Subtype used for disassembly */\ | 707 | u8 disasm_opcode; /* Subtype used for disassembly */\ |
| 708 | char aml_op_name[16]) /* Op name (debug only) */ | 708 | char aml_op_name[16]) /* Op name (debug only) */ |
| 709 | 709 | ||
| 710 | #define ACPI_DASM_BUFFER 0x00 | 710 | /* Flags for disasm_flags field above */ |
| 711 | #define ACPI_DASM_RESOURCE 0x01 | 711 | |
| 712 | #define ACPI_DASM_STRING 0x02 | 712 | #define ACPI_DASM_BUFFER 0x00 /* Buffer is a simple data buffer */ |
| 713 | #define ACPI_DASM_UNICODE 0x03 | 713 | #define ACPI_DASM_RESOURCE 0x01 /* Buffer is a Resource Descriptor */ |
| 714 | #define ACPI_DASM_EISAID 0x04 | 714 | #define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */ |
| 715 | #define ACPI_DASM_MATCHOP 0x05 | 715 | #define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */ |
| 716 | #define ACPI_DASM_LNOT_PREFIX 0x06 | 716 | #define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */ |
| 717 | #define ACPI_DASM_LNOT_SUFFIX 0x07 | 717 | #define ACPI_DASM_EISAID 0x05 /* Integer is an EISAID */ |
| 718 | #define ACPI_DASM_IGNORE 0x08 | 718 | #define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */ |
| 719 | #define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */ | ||
| 720 | #define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */ | ||
| 721 | #define ACPI_DASM_IGNORE 0x09 /* Not used at this time */ | ||
| 719 | 722 | ||
| 720 | /* | 723 | /* |
| 721 | * Generic operation (for example: If, While, Store) | 724 | * Generic operation (for example: If, While, Store) |
| @@ -932,6 +935,7 @@ struct acpi_bit_register_info { | |||
| 932 | #define ACPI_OSI_WIN_VISTA_SP1 0x09 | 935 | #define ACPI_OSI_WIN_VISTA_SP1 0x09 |
| 933 | #define ACPI_OSI_WIN_VISTA_SP2 0x0A | 936 | #define ACPI_OSI_WIN_VISTA_SP2 0x0A |
| 934 | #define ACPI_OSI_WIN_7 0x0B | 937 | #define ACPI_OSI_WIN_7 0x0B |
| 938 | #define ACPI_OSI_WIN_8 0x0C | ||
| 935 | 939 | ||
| 936 | #define ACPI_ALWAYS_ILLEGAL 0x00 | 940 | #define ACPI_ALWAYS_ILLEGAL 0x00 |
| 937 | 941 | ||
| @@ -1024,6 +1028,7 @@ struct acpi_port_info { | |||
| 1024 | ****************************************************************************/ | 1028 | ****************************************************************************/ |
| 1025 | 1029 | ||
| 1026 | struct acpi_db_method_info { | 1030 | struct acpi_db_method_info { |
| 1031 | acpi_handle method; | ||
| 1027 | acpi_handle main_thread_gate; | 1032 | acpi_handle main_thread_gate; |
| 1028 | acpi_handle thread_complete_gate; | 1033 | acpi_handle thread_complete_gate; |
| 1029 | acpi_thread_id *threads; | 1034 | acpi_thread_id *threads; |
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 832b6198652e..a7f68c47f517 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h | |||
| @@ -277,10 +277,33 @@ | |||
| 277 | 277 | ||
| 278 | /* Bitfields within ACPI registers */ | 278 | /* Bitfields within ACPI registers */ |
| 279 | 279 | ||
| 280 | #define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask) | 280 | #define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) \ |
| 281 | #define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask) | 281 | ((val << pos) & mask) |
| 282 | 282 | ||
| 283 | #define ACPI_INSERT_BITS(target, mask, source) target = ((target & (~(mask))) | (source & mask)) | 283 | #define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) \ |
| 284 | reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask) | ||
| 285 | |||
| 286 | #define ACPI_INSERT_BITS(target, mask, source) \ | ||
| 287 | target = ((target & (~(mask))) | (source & mask)) | ||
| 288 | |||
| 289 | /* Generic bitfield macros and masks */ | ||
| 290 | |||
| 291 | #define ACPI_GET_BITS(source_ptr, position, mask) \ | ||
| 292 | ((*source_ptr >> position) & mask) | ||
| 293 | |||
| 294 | #define ACPI_SET_BITS(target_ptr, position, mask, value) \ | ||
| 295 | (*target_ptr |= ((value & mask) << position)) | ||
| 296 | |||
| 297 | #define ACPI_1BIT_MASK 0x00000001 | ||
| 298 | #define ACPI_2BIT_MASK 0x00000003 | ||
| 299 | #define ACPI_3BIT_MASK 0x00000007 | ||
| 300 | #define ACPI_4BIT_MASK 0x0000000F | ||
| 301 | #define ACPI_5BIT_MASK 0x0000001F | ||
| 302 | #define ACPI_6BIT_MASK 0x0000003F | ||
| 303 | #define ACPI_7BIT_MASK 0x0000007F | ||
| 304 | #define ACPI_8BIT_MASK 0x000000FF | ||
| 305 | #define ACPI_16BIT_MASK 0x0000FFFF | ||
| 306 | #define ACPI_24BIT_MASK 0x00FFFFFF | ||
| 284 | 307 | ||
| 285 | /* | 308 | /* |
| 286 | * An object of type struct acpi_namespace_node can appear in some contexts | 309 | * An object of type struct acpi_namespace_node can appear in some contexts |
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 552aa3a50c84..557510084c7a 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c | |||
| @@ -230,6 +230,20 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | |||
| 230 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; | 230 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; |
| 231 | break; | 231 | break; |
| 232 | 232 | ||
| 233 | case ACPI_TYPE_METHOD: | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Allow scope change to root during execution of module-level | ||
| 237 | * code. Root is typed METHOD during this time. | ||
| 238 | */ | ||
| 239 | if ((node == acpi_gbl_root_node) && | ||
| 240 | (walk_state-> | ||
| 241 | parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | |||
| 245 | /*lint -fallthrough */ | ||
| 246 | |||
| 233 | default: | 247 | default: |
| 234 | 248 | ||
| 235 | /* All other types are an error */ | 249 | /* All other types are an error */ |
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index ae7147724763..89c0114210c0 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c | |||
| @@ -230,6 +230,20 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | |||
| 230 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; | 230 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; |
| 231 | break; | 231 | break; |
| 232 | 232 | ||
| 233 | case ACPI_TYPE_METHOD: | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Allow scope change to root during execution of module-level | ||
| 237 | * code. Root is typed METHOD during this time. | ||
| 238 | */ | ||
| 239 | if ((node == acpi_gbl_root_node) && | ||
| 240 | (walk_state-> | ||
| 241 | parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | |||
| 245 | /*lint -fallthrough */ | ||
| 246 | |||
| 233 | default: | 247 | default: |
| 234 | 248 | ||
| 235 | /* All other types are an error */ | 249 | /* All other types are an error */ |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index afbd5cb391f6..ef0193d74b5d 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
| @@ -80,8 +80,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) | |||
| 80 | return_ACPI_STATUS(AE_NOT_EXIST); | 80 | return_ACPI_STATUS(AE_NOT_EXIST); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, | 83 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); |
| 84 | gpe_register_info); | ||
| 85 | 84 | ||
| 86 | /* Clear the run bit up front */ | 85 | /* Clear the run bit up front */ |
| 87 | 86 | ||
| @@ -379,6 +378,18 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
| 379 | */ | 378 | */ |
| 380 | if (!(gpe_register_info->enable_for_run | | 379 | if (!(gpe_register_info->enable_for_run | |
| 381 | gpe_register_info->enable_for_wake)) { | 380 | gpe_register_info->enable_for_wake)) { |
| 381 | ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, | ||
| 382 | "Ignore disabled registers for GPE%02X-GPE%02X: " | ||
| 383 | "RunEnable=%02X, WakeEnable=%02X\n", | ||
| 384 | gpe_register_info-> | ||
| 385 | base_gpe_number, | ||
| 386 | gpe_register_info-> | ||
| 387 | base_gpe_number + | ||
| 388 | (ACPI_GPE_REGISTER_WIDTH - 1), | ||
| 389 | gpe_register_info-> | ||
| 390 | enable_for_run, | ||
| 391 | gpe_register_info-> | ||
| 392 | enable_for_wake)); | ||
| 382 | continue; | 393 | continue; |
| 383 | } | 394 | } |
| 384 | 395 | ||
| @@ -401,9 +412,14 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) | |||
| 401 | } | 412 | } |
| 402 | 413 | ||
| 403 | ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, | 414 | ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, |
| 404 | "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", | 415 | "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, " |
| 416 | "RunEnable=%02X, WakeEnable=%02X\n", | ||
| 405 | gpe_register_info->base_gpe_number, | 417 | gpe_register_info->base_gpe_number, |
| 406 | status_reg, enable_reg)); | 418 | gpe_register_info->base_gpe_number + |
| 419 | (ACPI_GPE_REGISTER_WIDTH - 1), | ||
| 420 | status_reg, enable_reg, | ||
| 421 | gpe_register_info->enable_for_run, | ||
| 422 | gpe_register_info->enable_for_wake)); | ||
| 407 | 423 | ||
| 408 | /* Check if there is anything active at all in this register */ | 424 | /* Check if there is anything active at all in this register */ |
| 409 | 425 | ||
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 6affbdb4b88c..87c5f2332260 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
| @@ -357,8 +357,7 @@ acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 ac | |||
| 357 | goto unlock_and_exit; | 357 | goto unlock_and_exit; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | register_bit = | 360 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); |
| 361 | acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); | ||
| 362 | 361 | ||
| 363 | /* Perform the action */ | 362 | /* Perform the action */ |
| 364 | 363 | ||
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 25bd28c4ae8d..db4076580e2b 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c | |||
| @@ -60,7 +60,6 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 60 | * FUNCTION: acpi_hw_get_gpe_register_bit | 60 | * FUNCTION: acpi_hw_get_gpe_register_bit |
| 61 | * | 61 | * |
| 62 | * PARAMETERS: gpe_event_info - Info block for the GPE | 62 | * PARAMETERS: gpe_event_info - Info block for the GPE |
| 63 | * gpe_register_info - Info block for the GPE register | ||
| 64 | * | 63 | * |
| 65 | * RETURN: Register mask with a one in the GPE bit position | 64 | * RETURN: Register mask with a one in the GPE bit position |
| 66 | * | 65 | * |
| @@ -69,11 +68,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 69 | * | 68 | * |
| 70 | ******************************************************************************/ | 69 | ******************************************************************************/ |
| 71 | 70 | ||
| 72 | u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, | 71 | u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) |
| 73 | struct acpi_gpe_register_info *gpe_register_info) | ||
| 74 | { | 72 | { |
| 75 | return (u32)1 << (gpe_event_info->gpe_number - | 73 | return (u32)1 << (gpe_event_info->gpe_number - |
| 76 | gpe_register_info->base_gpe_number); | 74 | gpe_event_info->register_info->base_gpe_number); |
| 77 | } | 75 | } |
| 78 | 76 | ||
| 79 | /****************************************************************************** | 77 | /****************************************************************************** |
| @@ -115,8 +113,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) | |||
| 115 | 113 | ||
| 116 | /* Set or clear just the bit that corresponds to this GPE */ | 114 | /* Set or clear just the bit that corresponds to this GPE */ |
| 117 | 115 | ||
| 118 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, | 116 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); |
| 119 | gpe_register_info); | ||
| 120 | switch (action) { | 117 | switch (action) { |
| 121 | case ACPI_GPE_CONDITIONAL_ENABLE: | 118 | case ACPI_GPE_CONDITIONAL_ENABLE: |
| 122 | 119 | ||
| @@ -178,8 +175,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) | |||
| 178 | * Write a one to the appropriate bit in the status register to | 175 | * Write a one to the appropriate bit in the status register to |
| 179 | * clear this GPE. | 176 | * clear this GPE. |
| 180 | */ | 177 | */ |
| 181 | register_bit = | 178 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); |
| 182 | acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); | ||
| 183 | 179 | ||
| 184 | status = acpi_hw_write(register_bit, | 180 | status = acpi_hw_write(register_bit, |
| 185 | &gpe_register_info->status_address); | 181 | &gpe_register_info->status_address); |
| @@ -222,8 +218,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, | |||
| 222 | 218 | ||
| 223 | /* Get the register bitmask for this GPE */ | 219 | /* Get the register bitmask for this GPE */ |
| 224 | 220 | ||
| 225 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info, | 221 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); |
| 226 | gpe_register_info); | ||
| 227 | 222 | ||
| 228 | /* GPE currently enabled? (enabled for runtime?) */ | 223 | /* GPE currently enabled? (enabled for runtime?) */ |
| 229 | 224 | ||
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 1f165a750ae2..0ff1ecea5c3a 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c | |||
| @@ -381,7 +381,6 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) | |||
| 381 | * FUNCTION: acpi_leave_sleep_state_prep | 381 | * FUNCTION: acpi_leave_sleep_state_prep |
| 382 | * | 382 | * |
| 383 | * PARAMETERS: sleep_state - Which sleep state we are exiting | 383 | * PARAMETERS: sleep_state - Which sleep state we are exiting |
| 384 | * flags - ACPI_EXECUTE_BFS to run optional method | ||
| 385 | * | 384 | * |
| 386 | * RETURN: Status | 385 | * RETURN: Status |
| 387 | * | 386 | * |
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 7ee4e6aeb0a2..2526aaf945ee 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c | |||
| @@ -264,7 +264,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, | |||
| 264 | switch (type) { | 264 | switch (type) { |
| 265 | case ACPI_TYPE_PROCESSOR: | 265 | case ACPI_TYPE_PROCESSOR: |
| 266 | 266 | ||
| 267 | acpi_os_printf("ID %X Len %.4X Addr %p\n", | 267 | acpi_os_printf("ID %02X Len %02X Addr %p\n", |
| 268 | obj_desc->processor.proc_id, | 268 | obj_desc->processor.proc_id, |
| 269 | obj_desc->processor.length, | 269 | obj_desc->processor.length, |
| 270 | ACPI_CAST_PTR(void, | 270 | ACPI_CAST_PTR(void, |
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 74f97d74db1c..70f9d787c82c 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c | |||
| @@ -350,6 +350,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header | |||
| 350 | acpi_status acpi_tb_resize_root_table_list(void) | 350 | acpi_status acpi_tb_resize_root_table_list(void) |
| 351 | { | 351 | { |
| 352 | struct acpi_table_desc *tables; | 352 | struct acpi_table_desc *tables; |
| 353 | u32 table_count; | ||
| 353 | 354 | ||
| 354 | ACPI_FUNCTION_TRACE(tb_resize_root_table_list); | 355 | ACPI_FUNCTION_TRACE(tb_resize_root_table_list); |
| 355 | 356 | ||
| @@ -363,8 +364,13 @@ acpi_status acpi_tb_resize_root_table_list(void) | |||
| 363 | 364 | ||
| 364 | /* Increase the Table Array size */ | 365 | /* Increase the Table Array size */ |
| 365 | 366 | ||
| 366 | tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. | 367 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { |
| 367 | max_table_count + | 368 | table_count = acpi_gbl_root_table_list.max_table_count; |
| 369 | } else { | ||
| 370 | table_count = acpi_gbl_root_table_list.current_table_count; | ||
| 371 | } | ||
| 372 | |||
| 373 | tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + | ||
| 368 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * | 374 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * |
| 369 | sizeof(struct acpi_table_desc)); | 375 | sizeof(struct acpi_table_desc)); |
| 370 | if (!tables) { | 376 | if (!tables) { |
| @@ -377,8 +383,8 @@ acpi_status acpi_tb_resize_root_table_list(void) | |||
| 377 | 383 | ||
| 378 | if (acpi_gbl_root_table_list.tables) { | 384 | if (acpi_gbl_root_table_list.tables) { |
| 379 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, | 385 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, |
| 380 | (acpi_size) acpi_gbl_root_table_list. | 386 | (acpi_size) table_count * |
| 381 | max_table_count * sizeof(struct acpi_table_desc)); | 387 | sizeof(struct acpi_table_desc)); |
| 382 | 388 | ||
| 383 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | 389 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { |
| 384 | ACPI_FREE(acpi_gbl_root_table_list.tables); | 390 | ACPI_FREE(acpi_gbl_root_table_list.tables); |
| @@ -386,9 +392,9 @@ acpi_status acpi_tb_resize_root_table_list(void) | |||
| 386 | } | 392 | } |
| 387 | 393 | ||
| 388 | acpi_gbl_root_table_list.tables = tables; | 394 | acpi_gbl_root_table_list.tables = tables; |
| 389 | acpi_gbl_root_table_list.max_table_count += | 395 | acpi_gbl_root_table_list.max_table_count = |
| 390 | ACPI_ROOT_TABLE_SIZE_INCREMENT; | 396 | table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; |
| 391 | acpi_gbl_root_table_list.flags |= (u8)ACPI_ROOT_ORIGIN_ALLOCATED; | 397 | acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; |
| 392 | 398 | ||
| 393 | return_ACPI_STATUS(AE_OK); | 399 | return_ACPI_STATUS(AE_OK); |
| 394 | } | 400 | } |
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 29e51bc01383..21101262e47a 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c | |||
| @@ -159,14 +159,12 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, | |||
| 159 | * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the | 159 | * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the |
| 160 | * root list from the previously provided scratch area. Should | 160 | * root list from the previously provided scratch area. Should |
| 161 | * be called once dynamic memory allocation is available in the | 161 | * be called once dynamic memory allocation is available in the |
| 162 | * kernel | 162 | * kernel. |
| 163 | * | 163 | * |
| 164 | ******************************************************************************/ | 164 | ******************************************************************************/ |
| 165 | acpi_status acpi_reallocate_root_table(void) | 165 | acpi_status acpi_reallocate_root_table(void) |
| 166 | { | 166 | { |
| 167 | struct acpi_table_desc *tables; | 167 | acpi_status status; |
| 168 | acpi_size new_size; | ||
| 169 | acpi_size current_size; | ||
| 170 | 168 | ||
| 171 | ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); | 169 | ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); |
| 172 | 170 | ||
| @@ -178,39 +176,10 @@ acpi_status acpi_reallocate_root_table(void) | |||
| 178 | return_ACPI_STATUS(AE_SUPPORT); | 176 | return_ACPI_STATUS(AE_SUPPORT); |
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | /* | 179 | acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE; |
| 182 | * Get the current size of the root table and add the default | ||
| 183 | * increment to create the new table size. | ||
| 184 | */ | ||
| 185 | current_size = (acpi_size) | ||
| 186 | acpi_gbl_root_table_list.current_table_count * | ||
| 187 | sizeof(struct acpi_table_desc); | ||
| 188 | |||
| 189 | new_size = current_size + | ||
| 190 | (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof(struct acpi_table_desc)); | ||
| 191 | |||
| 192 | /* Create new array and copy the old array */ | ||
| 193 | |||
| 194 | tables = ACPI_ALLOCATE_ZEROED(new_size); | ||
| 195 | if (!tables) { | ||
| 196 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
| 197 | } | ||
| 198 | 180 | ||
| 199 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, current_size); | 181 | status = acpi_tb_resize_root_table_list(); |
| 200 | 182 | return_ACPI_STATUS(status); | |
| 201 | /* | ||
| 202 | * Update the root table descriptor. The new size will be the current | ||
| 203 | * number of tables plus the increment, independent of the reserved | ||
| 204 | * size of the original table list. | ||
| 205 | */ | ||
| 206 | acpi_gbl_root_table_list.tables = tables; | ||
| 207 | acpi_gbl_root_table_list.max_table_count = | ||
| 208 | acpi_gbl_root_table_list.current_table_count + | ||
| 209 | ACPI_ROOT_TABLE_SIZE_INCREMENT; | ||
| 210 | acpi_gbl_root_table_list.flags = | ||
| 211 | ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; | ||
| 212 | |||
| 213 | return_ACPI_STATUS(AE_OK); | ||
| 214 | } | 183 | } |
| 215 | 184 | ||
| 216 | /******************************************************************************* | 185 | /******************************************************************************* |
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 34ef0bd7e4b4..676285d6116d 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c | |||
| @@ -73,6 +73,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { | |||
| 73 | {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ | 73 | {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ |
| 74 | {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ | 74 | {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ |
| 75 | {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ | 75 | {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ |
| 76 | {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ | ||
| 76 | 77 | ||
| 77 | /* Feature Group Strings */ | 78 | /* Feature Group Strings */ |
| 78 | 79 | ||
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 534179f1177b..b09632b4f5b3 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Module Name: utxface - External interfaces for "global" ACPI functions | 3 | * Module Name: utxface - External interfaces, miscellaneous utility functions |
| 4 | * | 4 | * |
| 5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
| 6 | 6 | ||
| @@ -53,271 +53,6 @@ | |||
| 53 | #define _COMPONENT ACPI_UTILITIES | 53 | #define _COMPONENT ACPI_UTILITIES |
| 54 | ACPI_MODULE_NAME("utxface") | 54 | ACPI_MODULE_NAME("utxface") |
| 55 | 55 | ||
| 56 | #ifndef ACPI_ASL_COMPILER | ||
| 57 | /******************************************************************************* | ||
| 58 | * | ||
| 59 | * FUNCTION: acpi_initialize_subsystem | ||
| 60 | * | ||
| 61 | * PARAMETERS: None | ||
| 62 | * | ||
| 63 | * RETURN: Status | ||
| 64 | * | ||
| 65 | * DESCRIPTION: Initializes all global variables. This is the first function | ||
| 66 | * called, so any early initialization belongs here. | ||
| 67 | * | ||
| 68 | ******************************************************************************/ | ||
| 69 | acpi_status __init acpi_initialize_subsystem(void) | ||
| 70 | { | ||
| 71 | acpi_status status; | ||
| 72 | |||
| 73 | ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); | ||
| 74 | |||
| 75 | acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; | ||
| 76 | ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); | ||
| 77 | |||
| 78 | /* Initialize the OS-Dependent layer */ | ||
| 79 | |||
| 80 | status = acpi_os_initialize(); | ||
| 81 | if (ACPI_FAILURE(status)) { | ||
| 82 | ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); | ||
| 83 | return_ACPI_STATUS(status); | ||
| 84 | } | ||
| 85 | |||
| 86 | /* Initialize all globals used by the subsystem */ | ||
| 87 | |||
| 88 | status = acpi_ut_init_globals(); | ||
| 89 | if (ACPI_FAILURE(status)) { | ||
| 90 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 91 | "During initialization of globals")); | ||
| 92 | return_ACPI_STATUS(status); | ||
| 93 | } | ||
| 94 | |||
| 95 | /* Create the default mutex objects */ | ||
| 96 | |||
| 97 | status = acpi_ut_mutex_initialize(); | ||
| 98 | if (ACPI_FAILURE(status)) { | ||
| 99 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 100 | "During Global Mutex creation")); | ||
| 101 | return_ACPI_STATUS(status); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Initialize the namespace manager and | ||
| 106 | * the root of the namespace tree | ||
| 107 | */ | ||
| 108 | status = acpi_ns_root_initialize(); | ||
| 109 | if (ACPI_FAILURE(status)) { | ||
| 110 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 111 | "During Namespace initialization")); | ||
| 112 | return_ACPI_STATUS(status); | ||
| 113 | } | ||
| 114 | |||
| 115 | /* Initialize the global OSI interfaces list with the static names */ | ||
| 116 | |||
| 117 | status = acpi_ut_initialize_interfaces(); | ||
| 118 | if (ACPI_FAILURE(status)) { | ||
| 119 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 120 | "During OSI interfaces initialization")); | ||
| 121 | return_ACPI_STATUS(status); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* If configured, initialize the AML debugger */ | ||
| 125 | |||
| 126 | ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); | ||
| 127 | return_ACPI_STATUS(status); | ||
| 128 | } | ||
| 129 | |||
| 130 | /******************************************************************************* | ||
| 131 | * | ||
| 132 | * FUNCTION: acpi_enable_subsystem | ||
| 133 | * | ||
| 134 | * PARAMETERS: flags - Init/enable Options | ||
| 135 | * | ||
| 136 | * RETURN: Status | ||
| 137 | * | ||
| 138 | * DESCRIPTION: Completes the subsystem initialization including hardware. | ||
| 139 | * Puts system into ACPI mode if it isn't already. | ||
| 140 | * | ||
| 141 | ******************************************************************************/ | ||
| 142 | acpi_status acpi_enable_subsystem(u32 flags) | ||
| 143 | { | ||
| 144 | acpi_status status = AE_OK; | ||
| 145 | |||
| 146 | ACPI_FUNCTION_TRACE(acpi_enable_subsystem); | ||
| 147 | |||
| 148 | #if (!ACPI_REDUCED_HARDWARE) | ||
| 149 | |||
| 150 | /* Enable ACPI mode */ | ||
| 151 | |||
| 152 | if (!(flags & ACPI_NO_ACPI_ENABLE)) { | ||
| 153 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 154 | "[Init] Going into ACPI mode\n")); | ||
| 155 | |||
| 156 | acpi_gbl_original_mode = acpi_hw_get_mode(); | ||
| 157 | |||
| 158 | status = acpi_enable(); | ||
| 159 | if (ACPI_FAILURE(status)) { | ||
| 160 | ACPI_WARNING((AE_INFO, "AcpiEnable failed")); | ||
| 161 | return_ACPI_STATUS(status); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /* | ||
| 166 | * Obtain a permanent mapping for the FACS. This is required for the | ||
| 167 | * Global Lock and the Firmware Waking Vector | ||
| 168 | */ | ||
| 169 | status = acpi_tb_initialize_facs(); | ||
| 170 | if (ACPI_FAILURE(status)) { | ||
| 171 | ACPI_WARNING((AE_INFO, "Could not map the FACS table")); | ||
| 172 | return_ACPI_STATUS(status); | ||
| 173 | } | ||
| 174 | #endif /* !ACPI_REDUCED_HARDWARE */ | ||
| 175 | |||
| 176 | /* | ||
| 177 | * Install the default op_region handlers. These are installed unless | ||
| 178 | * other handlers have already been installed via the | ||
| 179 | * install_address_space_handler interface. | ||
| 180 | */ | ||
| 181 | if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { | ||
| 182 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 183 | "[Init] Installing default address space handlers\n")); | ||
| 184 | |||
| 185 | status = acpi_ev_install_region_handlers(); | ||
| 186 | if (ACPI_FAILURE(status)) { | ||
| 187 | return_ACPI_STATUS(status); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | #if (!ACPI_REDUCED_HARDWARE) | ||
| 191 | /* | ||
| 192 | * Initialize ACPI Event handling (Fixed and General Purpose) | ||
| 193 | * | ||
| 194 | * Note1: We must have the hardware and events initialized before we can | ||
| 195 | * execute any control methods safely. Any control method can require | ||
| 196 | * ACPI hardware support, so the hardware must be fully initialized before | ||
| 197 | * any method execution! | ||
| 198 | * | ||
| 199 | * Note2: Fixed events are initialized and enabled here. GPEs are | ||
| 200 | * initialized, but cannot be enabled until after the hardware is | ||
| 201 | * completely initialized (SCI and global_lock activated) | ||
| 202 | */ | ||
| 203 | if (!(flags & ACPI_NO_EVENT_INIT)) { | ||
| 204 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 205 | "[Init] Initializing ACPI events\n")); | ||
| 206 | |||
| 207 | status = acpi_ev_initialize_events(); | ||
| 208 | if (ACPI_FAILURE(status)) { | ||
| 209 | return_ACPI_STATUS(status); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Install the SCI handler and Global Lock handler. This completes the | ||
| 215 | * hardware initialization. | ||
| 216 | */ | ||
| 217 | if (!(flags & ACPI_NO_HANDLER_INIT)) { | ||
| 218 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 219 | "[Init] Installing SCI/GL handlers\n")); | ||
| 220 | |||
| 221 | status = acpi_ev_install_xrupt_handlers(); | ||
| 222 | if (ACPI_FAILURE(status)) { | ||
| 223 | return_ACPI_STATUS(status); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | #endif /* !ACPI_REDUCED_HARDWARE */ | ||
| 227 | |||
| 228 | return_ACPI_STATUS(status); | ||
| 229 | } | ||
| 230 | |||
| 231 | ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) | ||
| 232 | |||
| 233 | /******************************************************************************* | ||
| 234 | * | ||
| 235 | * FUNCTION: acpi_initialize_objects | ||
| 236 | * | ||
| 237 | * PARAMETERS: flags - Init/enable Options | ||
| 238 | * | ||
| 239 | * RETURN: Status | ||
| 240 | * | ||
| 241 | * DESCRIPTION: Completes namespace initialization by initializing device | ||
| 242 | * objects and executing AML code for Regions, buffers, etc. | ||
| 243 | * | ||
| 244 | ******************************************************************************/ | ||
| 245 | acpi_status acpi_initialize_objects(u32 flags) | ||
| 246 | { | ||
| 247 | acpi_status status = AE_OK; | ||
| 248 | |||
| 249 | ACPI_FUNCTION_TRACE(acpi_initialize_objects); | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Run all _REG methods | ||
| 253 | * | ||
| 254 | * Note: Any objects accessed by the _REG methods will be automatically | ||
| 255 | * initialized, even if they contain executable AML (see the call to | ||
| 256 | * acpi_ns_initialize_objects below). | ||
| 257 | */ | ||
| 258 | if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { | ||
| 259 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 260 | "[Init] Executing _REG OpRegion methods\n")); | ||
| 261 | |||
| 262 | status = acpi_ev_initialize_op_regions(); | ||
| 263 | if (ACPI_FAILURE(status)) { | ||
| 264 | return_ACPI_STATUS(status); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Execute any module-level code that was detected during the table load | ||
| 270 | * phase. Although illegal since ACPI 2.0, there are many machines that | ||
| 271 | * contain this type of code. Each block of detected executable AML code | ||
| 272 | * outside of any control method is wrapped with a temporary control | ||
| 273 | * method object and placed on a global list. The methods on this list | ||
| 274 | * are executed below. | ||
| 275 | */ | ||
| 276 | acpi_ns_exec_module_code_list(); | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Initialize the objects that remain uninitialized. This runs the | ||
| 280 | * executable AML that may be part of the declaration of these objects: | ||
| 281 | * operation_regions, buffer_fields, Buffers, and Packages. | ||
| 282 | */ | ||
| 283 | if (!(flags & ACPI_NO_OBJECT_INIT)) { | ||
| 284 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 285 | "[Init] Completing Initialization of ACPI Objects\n")); | ||
| 286 | |||
| 287 | status = acpi_ns_initialize_objects(); | ||
| 288 | if (ACPI_FAILURE(status)) { | ||
| 289 | return_ACPI_STATUS(status); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | /* | ||
| 294 | * Initialize all device objects in the namespace. This runs the device | ||
| 295 | * _STA and _INI methods. | ||
| 296 | */ | ||
| 297 | if (!(flags & ACPI_NO_DEVICE_INIT)) { | ||
| 298 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 299 | "[Init] Initializing ACPI Devices\n")); | ||
| 300 | |||
| 301 | status = acpi_ns_initialize_devices(); | ||
| 302 | if (ACPI_FAILURE(status)) { | ||
| 303 | return_ACPI_STATUS(status); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /* | ||
| 308 | * Empty the caches (delete the cached objects) on the assumption that | ||
| 309 | * the table load filled them up more than they will be at runtime -- | ||
| 310 | * thus wasting non-paged memory. | ||
| 311 | */ | ||
| 312 | status = acpi_purge_cached_objects(); | ||
| 313 | |||
| 314 | acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; | ||
| 315 | return_ACPI_STATUS(status); | ||
| 316 | } | ||
| 317 | |||
| 318 | ACPI_EXPORT_SYMBOL(acpi_initialize_objects) | ||
| 319 | |||
| 320 | #endif | ||
| 321 | /******************************************************************************* | 56 | /******************************************************************************* |
| 322 | * | 57 | * |
| 323 | * FUNCTION: acpi_terminate | 58 | * FUNCTION: acpi_terminate |
| @@ -683,3 +418,90 @@ acpi_check_address_range(acpi_adr_space_type space_id, | |||
| 683 | 418 | ||
| 684 | ACPI_EXPORT_SYMBOL(acpi_check_address_range) | 419 | ACPI_EXPORT_SYMBOL(acpi_check_address_range) |
| 685 | #endif /* !ACPI_ASL_COMPILER */ | 420 | #endif /* !ACPI_ASL_COMPILER */ |
| 421 | /******************************************************************************* | ||
| 422 | * | ||
| 423 | * FUNCTION: acpi_decode_pld_buffer | ||
| 424 | * | ||
| 425 | * PARAMETERS: in_buffer - Buffer returned by _PLD method | ||
| 426 | * length - Length of the in_buffer | ||
| 427 | * return_buffer - Where the decode buffer is returned | ||
| 428 | * | ||
| 429 | * RETURN: Status and the decoded _PLD buffer. User must deallocate | ||
| 430 | * the buffer via ACPI_FREE. | ||
| 431 | * | ||
| 432 | * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into | ||
| 433 | * a local struct that is much more useful to an ACPI driver. | ||
| 434 | * | ||
| 435 | ******************************************************************************/ | ||
| 436 | acpi_status | ||
| 437 | acpi_decode_pld_buffer(u8 *in_buffer, | ||
| 438 | acpi_size length, struct acpi_pld_info ** return_buffer) | ||
| 439 | { | ||
| 440 | struct acpi_pld_info *pld_info; | ||
| 441 | u32 *buffer = ACPI_CAST_PTR(u32, in_buffer); | ||
| 442 | u32 dword; | ||
| 443 | |||
| 444 | /* Parameter validation */ | ||
| 445 | |||
| 446 | if (!in_buffer || !return_buffer || (length < 16)) { | ||
| 447 | return (AE_BAD_PARAMETER); | ||
| 448 | } | ||
| 449 | |||
| 450 | pld_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pld_info)); | ||
| 451 | if (!pld_info) { | ||
| 452 | return (AE_NO_MEMORY); | ||
| 453 | } | ||
| 454 | |||
| 455 | /* First 32-bit DWord */ | ||
| 456 | |||
| 457 | ACPI_MOVE_32_TO_32(&dword, &buffer[0]); | ||
| 458 | pld_info->revision = ACPI_PLD_GET_REVISION(&dword); | ||
| 459 | pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword); | ||
| 460 | pld_info->color = ACPI_PLD_GET_COLOR(&dword); | ||
| 461 | |||
| 462 | /* Second 32-bit DWord */ | ||
| 463 | |||
| 464 | ACPI_MOVE_32_TO_32(&dword, &buffer[1]); | ||
| 465 | pld_info->width = ACPI_PLD_GET_WIDTH(&dword); | ||
| 466 | pld_info->height = ACPI_PLD_GET_HEIGHT(&dword); | ||
| 467 | |||
| 468 | /* Third 32-bit DWord */ | ||
| 469 | |||
| 470 | ACPI_MOVE_32_TO_32(&dword, &buffer[2]); | ||
| 471 | pld_info->user_visible = ACPI_PLD_GET_USER_VISIBLE(&dword); | ||
| 472 | pld_info->dock = ACPI_PLD_GET_DOCK(&dword); | ||
| 473 | pld_info->lid = ACPI_PLD_GET_LID(&dword); | ||
| 474 | pld_info->panel = ACPI_PLD_GET_PANEL(&dword); | ||
| 475 | pld_info->vertical_position = ACPI_PLD_GET_VERTICAL(&dword); | ||
| 476 | pld_info->horizontal_position = ACPI_PLD_GET_HORIZONTAL(&dword); | ||
| 477 | pld_info->shape = ACPI_PLD_GET_SHAPE(&dword); | ||
| 478 | pld_info->group_orientation = ACPI_PLD_GET_ORIENTATION(&dword); | ||
| 479 | pld_info->group_token = ACPI_PLD_GET_TOKEN(&dword); | ||
| 480 | pld_info->group_position = ACPI_PLD_GET_POSITION(&dword); | ||
| 481 | pld_info->bay = ACPI_PLD_GET_BAY(&dword); | ||
| 482 | |||
| 483 | /* Fourth 32-bit DWord */ | ||
| 484 | |||
| 485 | ACPI_MOVE_32_TO_32(&dword, &buffer[3]); | ||
| 486 | pld_info->ejectable = ACPI_PLD_GET_EJECTABLE(&dword); | ||
| 487 | pld_info->ospm_eject_required = ACPI_PLD_GET_OSPM_EJECT(&dword); | ||
| 488 | pld_info->cabinet_number = ACPI_PLD_GET_CABINET(&dword); | ||
| 489 | pld_info->card_cage_number = ACPI_PLD_GET_CARD_CAGE(&dword); | ||
| 490 | pld_info->reference = ACPI_PLD_GET_REFERENCE(&dword); | ||
| 491 | pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword); | ||
| 492 | pld_info->order = ACPI_PLD_GET_ORDER(&dword); | ||
| 493 | |||
| 494 | if (length >= ACPI_PLD_BUFFER_SIZE) { | ||
| 495 | |||
| 496 | /* Fifth 32-bit DWord (Revision 2 of _PLD) */ | ||
| 497 | |||
| 498 | ACPI_MOVE_32_TO_32(&dword, &buffer[4]); | ||
| 499 | pld_info->vertical_offset = ACPI_PLD_GET_VERT_OFFSET(&dword); | ||
| 500 | pld_info->horizontal_offset = ACPI_PLD_GET_HORIZ_OFFSET(&dword); | ||
| 501 | } | ||
| 502 | |||
| 503 | *return_buffer = pld_info; | ||
| 504 | return (AE_OK); | ||
| 505 | } | ||
| 506 | |||
| 507 | ACPI_EXPORT_SYMBOL(acpi_decode_pld_buffer) | ||
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c new file mode 100644 index 000000000000..14f523627a5e --- /dev/null +++ b/drivers/acpi/acpica/utxfinit.c | |||
| @@ -0,0 +1,317 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * Module Name: utxfinit - External interfaces for ACPICA initialization | ||
| 4 | * | ||
| 5 | *****************************************************************************/ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * Copyright (C) 2000 - 2012, 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 <linux/export.h> | ||
| 45 | #include <acpi/acpi.h> | ||
| 46 | #include "accommon.h" | ||
| 47 | #include "acevents.h" | ||
| 48 | #include "acnamesp.h" | ||
| 49 | #include "acdebug.h" | ||
| 50 | #include "actables.h" | ||
| 51 | |||
| 52 | #define _COMPONENT ACPI_UTILITIES | ||
| 53 | ACPI_MODULE_NAME("utxfinit") | ||
| 54 | |||
| 55 | /******************************************************************************* | ||
| 56 | * | ||
| 57 | * FUNCTION: acpi_initialize_subsystem | ||
| 58 | * | ||
| 59 | * PARAMETERS: None | ||
| 60 | * | ||
| 61 | * RETURN: Status | ||
| 62 | * | ||
| 63 | * DESCRIPTION: Initializes all global variables. This is the first function | ||
| 64 | * called, so any early initialization belongs here. | ||
| 65 | * | ||
| 66 | ******************************************************************************/ | ||
| 67 | acpi_status acpi_initialize_subsystem(void) | ||
| 68 | { | ||
| 69 | acpi_status status; | ||
| 70 | |||
| 71 | ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); | ||
| 72 | |||
| 73 | acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE; | ||
| 74 | ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); | ||
| 75 | |||
| 76 | /* Initialize the OS-Dependent layer */ | ||
| 77 | |||
| 78 | status = acpi_os_initialize(); | ||
| 79 | if (ACPI_FAILURE(status)) { | ||
| 80 | ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization")); | ||
| 81 | return_ACPI_STATUS(status); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* Initialize all globals used by the subsystem */ | ||
| 85 | |||
| 86 | status = acpi_ut_init_globals(); | ||
| 87 | if (ACPI_FAILURE(status)) { | ||
| 88 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 89 | "During initialization of globals")); | ||
| 90 | return_ACPI_STATUS(status); | ||
| 91 | } | ||
| 92 | |||
| 93 | /* Create the default mutex objects */ | ||
| 94 | |||
| 95 | status = acpi_ut_mutex_initialize(); | ||
| 96 | if (ACPI_FAILURE(status)) { | ||
| 97 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 98 | "During Global Mutex creation")); | ||
| 99 | return_ACPI_STATUS(status); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Initialize the namespace manager and | ||
| 104 | * the root of the namespace tree | ||
| 105 | */ | ||
| 106 | status = acpi_ns_root_initialize(); | ||
| 107 | if (ACPI_FAILURE(status)) { | ||
| 108 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 109 | "During Namespace initialization")); | ||
| 110 | return_ACPI_STATUS(status); | ||
| 111 | } | ||
| 112 | |||
| 113 | /* Initialize the global OSI interfaces list with the static names */ | ||
| 114 | |||
| 115 | status = acpi_ut_initialize_interfaces(); | ||
| 116 | if (ACPI_FAILURE(status)) { | ||
| 117 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 118 | "During OSI interfaces initialization")); | ||
| 119 | return_ACPI_STATUS(status); | ||
| 120 | } | ||
| 121 | |||
| 122 | /* If configured, initialize the AML debugger */ | ||
| 123 | |||
| 124 | ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); | ||
| 125 | return_ACPI_STATUS(status); | ||
| 126 | } | ||
| 127 | ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem) | ||
| 128 | |||
| 129 | /******************************************************************************* | ||
| 130 | * | ||
| 131 | * FUNCTION: acpi_enable_subsystem | ||
| 132 | * | ||
| 133 | * PARAMETERS: flags - Init/enable Options | ||
| 134 | * | ||
| 135 | * RETURN: Status | ||
| 136 | * | ||
| 137 | * DESCRIPTION: Completes the subsystem initialization including hardware. | ||
| 138 | * Puts system into ACPI mode if it isn't already. | ||
| 139 | * | ||
| 140 | ******************************************************************************/ | ||
| 141 | acpi_status acpi_enable_subsystem(u32 flags) | ||
| 142 | { | ||
| 143 | acpi_status status = AE_OK; | ||
| 144 | |||
| 145 | ACPI_FUNCTION_TRACE(acpi_enable_subsystem); | ||
| 146 | |||
| 147 | #if (!ACPI_REDUCED_HARDWARE) | ||
| 148 | |||
| 149 | /* Enable ACPI mode */ | ||
| 150 | |||
| 151 | if (!(flags & ACPI_NO_ACPI_ENABLE)) { | ||
| 152 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 153 | "[Init] Going into ACPI mode\n")); | ||
| 154 | |||
| 155 | acpi_gbl_original_mode = acpi_hw_get_mode(); | ||
| 156 | |||
| 157 | status = acpi_enable(); | ||
| 158 | if (ACPI_FAILURE(status)) { | ||
| 159 | ACPI_WARNING((AE_INFO, "AcpiEnable failed")); | ||
| 160 | return_ACPI_STATUS(status); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Obtain a permanent mapping for the FACS. This is required for the | ||
| 166 | * Global Lock and the Firmware Waking Vector | ||
| 167 | */ | ||
| 168 | status = acpi_tb_initialize_facs(); | ||
| 169 | if (ACPI_FAILURE(status)) { | ||
| 170 | ACPI_WARNING((AE_INFO, "Could not map the FACS table")); | ||
| 171 | return_ACPI_STATUS(status); | ||
| 172 | } | ||
| 173 | #endif /* !ACPI_REDUCED_HARDWARE */ | ||
| 174 | |||
| 175 | /* | ||
| 176 | * Install the default op_region handlers. These are installed unless | ||
| 177 | * other handlers have already been installed via the | ||
| 178 | * install_address_space_handler interface. | ||
| 179 | */ | ||
| 180 | if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { | ||
| 181 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 182 | "[Init] Installing default address space handlers\n")); | ||
| 183 | |||
| 184 | status = acpi_ev_install_region_handlers(); | ||
| 185 | if (ACPI_FAILURE(status)) { | ||
| 186 | return_ACPI_STATUS(status); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | #if (!ACPI_REDUCED_HARDWARE) | ||
| 190 | /* | ||
| 191 | * Initialize ACPI Event handling (Fixed and General Purpose) | ||
| 192 | * | ||
| 193 | * Note1: We must have the hardware and events initialized before we can | ||
| 194 | * execute any control methods safely. Any control method can require | ||
| 195 | * ACPI hardware support, so the hardware must be fully initialized before | ||
| 196 | * any method execution! | ||
| 197 | * | ||
| 198 | * Note2: Fixed events are initialized and enabled here. GPEs are | ||
| 199 | * initialized, but cannot be enabled until after the hardware is | ||
| 200 | * completely initialized (SCI and global_lock activated) and the various | ||
| 201 | * initialization control methods are run (_REG, _STA, _INI) on the | ||
| 202 | * entire namespace. | ||
| 203 | */ | ||
| 204 | if (!(flags & ACPI_NO_EVENT_INIT)) { | ||
| 205 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 206 | "[Init] Initializing ACPI events\n")); | ||
| 207 | |||
| 208 | status = acpi_ev_initialize_events(); | ||
| 209 | if (ACPI_FAILURE(status)) { | ||
| 210 | return_ACPI_STATUS(status); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | /* | ||
| 215 | * Install the SCI handler and Global Lock handler. This completes the | ||
| 216 | * hardware initialization. | ||
| 217 | */ | ||
| 218 | if (!(flags & ACPI_NO_HANDLER_INIT)) { | ||
| 219 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 220 | "[Init] Installing SCI/GL handlers\n")); | ||
| 221 | |||
| 222 | status = acpi_ev_install_xrupt_handlers(); | ||
| 223 | if (ACPI_FAILURE(status)) { | ||
| 224 | return_ACPI_STATUS(status); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | #endif /* !ACPI_REDUCED_HARDWARE */ | ||
| 228 | |||
| 229 | return_ACPI_STATUS(status); | ||
| 230 | } | ||
| 231 | ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) | ||
| 232 | |||
| 233 | /******************************************************************************* | ||
| 234 | * | ||
| 235 | * FUNCTION: acpi_initialize_objects | ||
| 236 | * | ||
| 237 | * PARAMETERS: flags - Init/enable Options | ||
| 238 | * | ||
| 239 | * RETURN: Status | ||
| 240 | * | ||
| 241 | * DESCRIPTION: Completes namespace initialization by initializing device | ||
| 242 | * objects and executing AML code for Regions, buffers, etc. | ||
| 243 | * | ||
| 244 | ******************************************************************************/ | ||
| 245 | acpi_status acpi_initialize_objects(u32 flags) | ||
| 246 | { | ||
| 247 | acpi_status status = AE_OK; | ||
| 248 | |||
| 249 | ACPI_FUNCTION_TRACE(acpi_initialize_objects); | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Run all _REG methods | ||
| 253 | * | ||
| 254 | * Note: Any objects accessed by the _REG methods will be automatically | ||
| 255 | * initialized, even if they contain executable AML (see the call to | ||
| 256 | * acpi_ns_initialize_objects below). | ||
| 257 | */ | ||
| 258 | if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { | ||
| 259 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 260 | "[Init] Executing _REG OpRegion methods\n")); | ||
| 261 | |||
| 262 | status = acpi_ev_initialize_op_regions(); | ||
| 263 | if (ACPI_FAILURE(status)) { | ||
| 264 | return_ACPI_STATUS(status); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Execute any module-level code that was detected during the table load | ||
| 270 | * phase. Although illegal since ACPI 2.0, there are many machines that | ||
| 271 | * contain this type of code. Each block of detected executable AML code | ||
| 272 | * outside of any control method is wrapped with a temporary control | ||
| 273 | * method object and placed on a global list. The methods on this list | ||
| 274 | * are executed below. | ||
| 275 | */ | ||
| 276 | acpi_ns_exec_module_code_list(); | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Initialize the objects that remain uninitialized. This runs the | ||
| 280 | * executable AML that may be part of the declaration of these objects: | ||
| 281 | * operation_regions, buffer_fields, Buffers, and Packages. | ||
| 282 | */ | ||
| 283 | if (!(flags & ACPI_NO_OBJECT_INIT)) { | ||
| 284 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 285 | "[Init] Completing Initialization of ACPI Objects\n")); | ||
| 286 | |||
| 287 | status = acpi_ns_initialize_objects(); | ||
| 288 | if (ACPI_FAILURE(status)) { | ||
| 289 | return_ACPI_STATUS(status); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | /* | ||
| 294 | * Initialize all device objects in the namespace. This runs the device | ||
| 295 | * _STA and _INI methods. | ||
| 296 | */ | ||
| 297 | if (!(flags & ACPI_NO_DEVICE_INIT)) { | ||
| 298 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
| 299 | "[Init] Initializing ACPI Devices\n")); | ||
| 300 | |||
| 301 | status = acpi_ns_initialize_devices(); | ||
| 302 | if (ACPI_FAILURE(status)) { | ||
| 303 | return_ACPI_STATUS(status); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /* | ||
| 308 | * Empty the caches (delete the cached objects) on the assumption that | ||
| 309 | * the table load filled them up more than they will be at runtime -- | ||
| 310 | * thus wasting non-paged memory. | ||
| 311 | */ | ||
| 312 | status = acpi_purge_cached_objects(); | ||
| 313 | |||
| 314 | acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK; | ||
| 315 | return_ACPI_STATUS(status); | ||
| 316 | } | ||
| 317 | ACPI_EXPORT_SYMBOL(acpi_initialize_objects) | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e0596954290b..d59175efc428 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -994,8 +994,6 @@ static int __init acpi_bus_init(void) | |||
| 994 | status = acpi_ec_ecdt_probe(); | 994 | status = acpi_ec_ecdt_probe(); |
| 995 | /* Ignore result. Not having an ECDT is not fatal. */ | 995 | /* Ignore result. Not having an ECDT is not fatal. */ |
| 996 | 996 | ||
| 997 | acpi_bus_osc_support(); | ||
| 998 | |||
| 999 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); | 997 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); |
| 1000 | if (ACPI_FAILURE(status)) { | 998 | if (ACPI_FAILURE(status)) { |
| 1001 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); | 999 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); |
| @@ -1003,6 +1001,12 @@ static int __init acpi_bus_init(void) | |||
| 1003 | } | 1001 | } |
| 1004 | 1002 | ||
| 1005 | /* | 1003 | /* |
| 1004 | * _OSC method may exist in module level code, | ||
| 1005 | * so it must be run after ACPI_FULL_INITIALIZATION | ||
| 1006 | */ | ||
| 1007 | acpi_bus_osc_support(); | ||
| 1008 | |||
| 1009 | /* | ||
| 1006 | * _PDC control method may load dynamic SSDT tables, | 1010 | * _PDC control method may load dynamic SSDT tables, |
| 1007 | * and we need to install the table handler before that. | 1011 | * and we need to install the table handler before that. |
| 1008 | */ | 1012 | */ |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 314a3b84bbc7..f0d936b65e37 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
| @@ -450,15 +450,4 @@ static int acpi_button_remove(struct acpi_device *device, int type) | |||
| 450 | return 0; | 450 | return 0; |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | static int __init acpi_button_init(void) | 453 | module_acpi_driver(acpi_button_driver); |
| 454 | { | ||
| 455 | return acpi_bus_register_driver(&acpi_button_driver); | ||
| 456 | } | ||
| 457 | |||
| 458 | static void __exit acpi_button_exit(void) | ||
| 459 | { | ||
| 460 | acpi_bus_unregister_driver(&acpi_button_driver); | ||
| 461 | } | ||
| 462 | |||
| 463 | module_init(acpi_button_init); | ||
| 464 | module_exit(acpi_button_exit); | ||
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index bc36a476f1ab..3bd6a54702d6 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
| @@ -212,24 +212,4 @@ static int acpi_fan_resume(struct device *dev) | |||
| 212 | } | 212 | } |
| 213 | #endif | 213 | #endif |
| 214 | 214 | ||
| 215 | static int __init acpi_fan_init(void) | 215 | module_acpi_driver(acpi_fan_driver); |
| 216 | { | ||
| 217 | int result = 0; | ||
| 218 | |||
| 219 | result = acpi_bus_register_driver(&acpi_fan_driver); | ||
| 220 | if (result < 0) | ||
| 221 | return -ENODEV; | ||
| 222 | |||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | static void __exit acpi_fan_exit(void) | ||
| 227 | { | ||
| 228 | |||
| 229 | acpi_bus_unregister_driver(&acpi_fan_driver); | ||
| 230 | |||
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | module_init(acpi_fan_init); | ||
| 235 | module_exit(acpi_fan_exit); | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 243ee85e4d2e..d1a2d74033e9 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | static LIST_HEAD(bus_type_list); | 25 | static LIST_HEAD(bus_type_list); |
| 26 | static DECLARE_RWSEM(bus_type_sem); | 26 | static DECLARE_RWSEM(bus_type_sem); |
| 27 | 27 | ||
| 28 | #define PHYSICAL_NODE_STRING "physical_node" | ||
| 29 | |||
| 28 | int register_acpi_bus_type(struct acpi_bus_type *type) | 30 | int register_acpi_bus_type(struct acpi_bus_type *type) |
| 29 | { | 31 | { |
| 30 | if (acpi_disabled) | 32 | if (acpi_disabled) |
| @@ -124,84 +126,119 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address) | |||
| 124 | 126 | ||
| 125 | EXPORT_SYMBOL(acpi_get_child); | 127 | EXPORT_SYMBOL(acpi_get_child); |
| 126 | 128 | ||
| 127 | /* Link ACPI devices with physical devices */ | ||
| 128 | static void acpi_glue_data_handler(acpi_handle handle, | ||
| 129 | void *context) | ||
| 130 | { | ||
| 131 | /* we provide an empty handler */ | ||
| 132 | } | ||
| 133 | |||
| 134 | /* Note: a success call will increase reference count by one */ | ||
| 135 | struct device *acpi_get_physical_device(acpi_handle handle) | ||
| 136 | { | ||
| 137 | acpi_status status; | ||
| 138 | struct device *dev; | ||
| 139 | |||
| 140 | status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev); | ||
| 141 | if (ACPI_SUCCESS(status)) | ||
| 142 | return get_device(dev); | ||
| 143 | return NULL; | ||
| 144 | } | ||
| 145 | |||
| 146 | EXPORT_SYMBOL(acpi_get_physical_device); | ||
| 147 | |||
| 148 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 129 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
| 149 | { | 130 | { |
| 150 | struct acpi_device *acpi_dev; | 131 | struct acpi_device *acpi_dev; |
| 151 | acpi_status status; | 132 | acpi_status status; |
| 133 | struct acpi_device_physical_node *physical_node; | ||
| 134 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; | ||
| 135 | int retval = -EINVAL; | ||
| 152 | 136 | ||
| 153 | if (dev->archdata.acpi_handle) { | 137 | if (dev->archdata.acpi_handle) { |
| 154 | dev_warn(dev, "Drivers changed 'acpi_handle'\n"); | 138 | dev_warn(dev, "Drivers changed 'acpi_handle'\n"); |
| 155 | return -EINVAL; | 139 | return -EINVAL; |
| 156 | } | 140 | } |
| 141 | |||
| 157 | get_device(dev); | 142 | get_device(dev); |
| 158 | status = acpi_attach_data(handle, acpi_glue_data_handler, dev); | 143 | status = acpi_bus_get_device(handle, &acpi_dev); |
| 159 | if (ACPI_FAILURE(status)) { | 144 | if (ACPI_FAILURE(status)) |
| 160 | put_device(dev); | 145 | goto err; |
| 161 | return -EINVAL; | 146 | |
| 147 | physical_node = kzalloc(sizeof(struct acpi_device_physical_node), | ||
| 148 | GFP_KERNEL); | ||
| 149 | if (!physical_node) { | ||
| 150 | retval = -ENOMEM; | ||
| 151 | goto err; | ||
| 162 | } | 152 | } |
| 163 | dev->archdata.acpi_handle = handle; | ||
| 164 | 153 | ||
| 165 | status = acpi_bus_get_device(handle, &acpi_dev); | 154 | mutex_lock(&acpi_dev->physical_node_lock); |
| 166 | if (!ACPI_FAILURE(status)) { | 155 | /* allocate physical node id according to physical_node_id_bitmap */ |
| 167 | int ret; | 156 | physical_node->node_id = |
| 168 | 157 | find_first_zero_bit(acpi_dev->physical_node_id_bitmap, | |
| 169 | ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, | 158 | ACPI_MAX_PHYSICAL_NODE); |
| 170 | "firmware_node"); | 159 | if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { |
| 171 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | 160 | retval = -ENOSPC; |
| 172 | "physical_node"); | 161 | mutex_unlock(&acpi_dev->physical_node_lock); |
| 173 | if (acpi_dev->wakeup.flags.valid) | 162 | goto err; |
| 174 | device_set_wakeup_capable(dev, true); | ||
| 175 | } | 163 | } |
| 176 | 164 | ||
| 165 | set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); | ||
| 166 | physical_node->dev = dev; | ||
| 167 | list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); | ||
| 168 | acpi_dev->physical_node_count++; | ||
| 169 | mutex_unlock(&acpi_dev->physical_node_lock); | ||
| 170 | |||
| 171 | dev->archdata.acpi_handle = handle; | ||
| 172 | |||
| 173 | if (!physical_node->node_id) | ||
| 174 | strcpy(physical_node_name, PHYSICAL_NODE_STRING); | ||
| 175 | else | ||
| 176 | sprintf(physical_node_name, | ||
| 177 | "physical_node%d", physical_node->node_id); | ||
| 178 | retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | ||
| 179 | physical_node_name); | ||
| 180 | retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, | ||
| 181 | "firmware_node"); | ||
| 182 | |||
| 183 | if (acpi_dev->wakeup.flags.valid) | ||
| 184 | device_set_wakeup_capable(dev, true); | ||
| 185 | |||
| 177 | return 0; | 186 | return 0; |
| 187 | |||
| 188 | err: | ||
| 189 | put_device(dev); | ||
| 190 | return retval; | ||
| 178 | } | 191 | } |
| 179 | 192 | ||
| 180 | static int acpi_unbind_one(struct device *dev) | 193 | static int acpi_unbind_one(struct device *dev) |
| 181 | { | 194 | { |
| 195 | struct acpi_device_physical_node *entry; | ||
| 196 | struct acpi_device *acpi_dev; | ||
| 197 | acpi_status status; | ||
| 198 | struct list_head *node, *next; | ||
| 199 | |||
| 182 | if (!dev->archdata.acpi_handle) | 200 | if (!dev->archdata.acpi_handle) |
| 183 | return 0; | 201 | return 0; |
| 184 | if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { | ||
| 185 | struct acpi_device *acpi_dev; | ||
| 186 | 202 | ||
| 187 | /* acpi_get_physical_device increase refcnt by one */ | 203 | status = acpi_bus_get_device(dev->archdata.acpi_handle, |
| 188 | put_device(dev); | 204 | &acpi_dev); |
| 205 | if (ACPI_FAILURE(status)) | ||
| 206 | goto err; | ||
| 189 | 207 | ||
| 190 | if (!acpi_bus_get_device(dev->archdata.acpi_handle, | 208 | mutex_lock(&acpi_dev->physical_node_lock); |
| 191 | &acpi_dev)) { | 209 | list_for_each_safe(node, next, &acpi_dev->physical_node_list) { |
| 192 | sysfs_remove_link(&dev->kobj, "firmware_node"); | 210 | char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; |
| 193 | sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); | 211 | |
| 194 | } | 212 | entry = list_entry(node, struct acpi_device_physical_node, |
| 213 | node); | ||
| 214 | if (entry->dev != dev) | ||
| 215 | continue; | ||
| 216 | |||
| 217 | list_del(node); | ||
| 218 | clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap); | ||
| 195 | 219 | ||
| 196 | acpi_detach_data(dev->archdata.acpi_handle, | 220 | acpi_dev->physical_node_count--; |
| 197 | acpi_glue_data_handler); | 221 | |
| 222 | if (!entry->node_id) | ||
| 223 | strcpy(physical_node_name, PHYSICAL_NODE_STRING); | ||
| 224 | else | ||
| 225 | sprintf(physical_node_name, | ||
| 226 | "physical_node%d", entry->node_id); | ||
| 227 | |||
| 228 | sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); | ||
| 229 | sysfs_remove_link(&dev->kobj, "firmware_node"); | ||
| 198 | dev->archdata.acpi_handle = NULL; | 230 | dev->archdata.acpi_handle = NULL; |
| 199 | /* acpi_bind_one increase refcnt by one */ | 231 | /* acpi_bind_one increase refcnt by one */ |
| 200 | put_device(dev); | 232 | put_device(dev); |
| 201 | } else { | 233 | kfree(entry); |
| 202 | dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); | ||
| 203 | } | 234 | } |
| 235 | mutex_unlock(&acpi_dev->physical_node_lock); | ||
| 236 | |||
| 204 | return 0; | 237 | return 0; |
| 238 | |||
| 239 | err: | ||
| 240 | dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); | ||
| 241 | return -EINVAL; | ||
| 205 | } | 242 | } |
| 206 | 243 | ||
| 207 | static int acpi_platform_notify(struct device *dev) | 244 | static int acpi_platform_notify(struct device *dev) |
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index d0c1967f7597..20a0f2c3ca3b 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c | |||
| @@ -86,25 +86,7 @@ static struct acpi_driver acpi_hed_driver = { | |||
| 86 | .notify = acpi_hed_notify, | 86 | .notify = acpi_hed_notify, |
| 87 | }, | 87 | }, |
| 88 | }; | 88 | }; |
| 89 | 89 | module_acpi_driver(acpi_hed_driver); | |
| 90 | static int __init acpi_hed_init(void) | ||
| 91 | { | ||
| 92 | if (acpi_disabled) | ||
| 93 | return -ENODEV; | ||
| 94 | |||
| 95 | if (acpi_bus_register_driver(&acpi_hed_driver) < 0) | ||
| 96 | return -ENODEV; | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | static void __exit acpi_hed_exit(void) | ||
| 102 | { | ||
| 103 | acpi_bus_unregister_driver(&acpi_hed_driver); | ||
| 104 | } | ||
| 105 | |||
| 106 | module_init(acpi_hed_init); | ||
| 107 | module_exit(acpi_hed_exit); | ||
| 108 | 90 | ||
| 109 | ACPI_MODULE_NAME("hed"); | 91 | ACPI_MODULE_NAME("hed"); |
| 110 | MODULE_AUTHOR("Huang Ying"); | 92 | MODULE_AUTHOR("Huang Ying"); |
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 251c7b6273a9..27adb090bb30 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
| @@ -302,26 +302,41 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
| 302 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 302 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
| 303 | struct acpi_device *dev = | 303 | struct acpi_device *dev = |
| 304 | container_of(node, struct acpi_device, wakeup_list); | 304 | container_of(node, struct acpi_device, wakeup_list); |
| 305 | struct device *ldev; | 305 | struct acpi_device_physical_node *entry; |
| 306 | 306 | ||
| 307 | if (!dev->wakeup.flags.valid) | 307 | if (!dev->wakeup.flags.valid) |
| 308 | continue; | 308 | continue; |
| 309 | 309 | ||
| 310 | ldev = acpi_get_physical_device(dev->handle); | 310 | seq_printf(seq, "%s\t S%d\t", |
| 311 | seq_printf(seq, "%s\t S%d\t%c%-8s ", | ||
| 312 | dev->pnp.bus_id, | 311 | dev->pnp.bus_id, |
| 313 | (u32) dev->wakeup.sleep_state, | 312 | (u32) dev->wakeup.sleep_state); |
| 314 | dev->wakeup.flags.run_wake ? '*' : ' ', | 313 | |
| 315 | (device_may_wakeup(&dev->dev) | 314 | if (!dev->physical_node_count) |
| 316 | || (ldev && device_may_wakeup(ldev))) ? | 315 | seq_printf(seq, "%c%-8s\n", |
| 317 | "enabled" : "disabled"); | 316 | dev->wakeup.flags.run_wake ? |
| 318 | if (ldev) | 317 | '*' : ' ', "disabled"); |
| 319 | seq_printf(seq, "%s:%s", | 318 | else { |
| 320 | ldev->bus ? ldev->bus->name : "no-bus", | 319 | struct device *ldev; |
| 321 | dev_name(ldev)); | 320 | list_for_each_entry(entry, &dev->physical_node_list, |
| 322 | seq_printf(seq, "\n"); | 321 | node) { |
| 323 | put_device(ldev); | 322 | ldev = get_device(entry->dev); |
| 324 | 323 | if (!ldev) | |
| 324 | continue; | ||
| 325 | |||
| 326 | if (&entry->node != | ||
| 327 | dev->physical_node_list.next) | ||
| 328 | seq_printf(seq, "\t\t"); | ||
| 329 | |||
| 330 | seq_printf(seq, "%c%-8s %s:%s\n", | ||
| 331 | dev->wakeup.flags.run_wake ? '*' : ' ', | ||
| 332 | (device_may_wakeup(&dev->dev) || | ||
| 333 | (ldev && device_may_wakeup(ldev))) ? | ||
| 334 | "enabled" : "disabled", | ||
| 335 | ldev->bus ? ldev->bus->name : | ||
| 336 | "no-bus", dev_name(ldev)); | ||
| 337 | put_device(ldev); | ||
| 338 | } | ||
| 339 | } | ||
| 325 | } | 340 | } |
| 326 | mutex_unlock(&acpi_device_lock); | 341 | mutex_unlock(&acpi_device_lock); |
| 327 | return 0; | 342 | return 0; |
| @@ -329,12 +344,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
| 329 | 344 | ||
| 330 | static void physical_device_enable_wakeup(struct acpi_device *adev) | 345 | static void physical_device_enable_wakeup(struct acpi_device *adev) |
| 331 | { | 346 | { |
| 332 | struct device *dev = acpi_get_physical_device(adev->handle); | 347 | struct acpi_device_physical_node *entry; |
| 333 | 348 | ||
| 334 | if (dev && device_can_wakeup(dev)) { | 349 | list_for_each_entry(entry, |
| 335 | bool enable = !device_may_wakeup(dev); | 350 | &adev->physical_node_list, node) |
| 336 | device_set_wakeup_enable(dev, enable); | 351 | if (entry->dev && device_can_wakeup(entry->dev)) { |
| 337 | } | 352 | bool enable = !device_may_wakeup(entry->dev); |
| 353 | device_set_wakeup_enable(entry->dev, enable); | ||
| 354 | } | ||
| 338 | } | 355 | } |
| 339 | 356 | ||
| 340 | static ssize_t | 357 | static ssize_t |
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index f8d2a472795c..cf6129a8af7c 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c | |||
| @@ -310,23 +310,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type) | |||
| 310 | return 0; | 310 | return 0; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static int __init acpi_smb_hc_init(void) | 313 | module_acpi_driver(acpi_smb_hc_driver); |
| 314 | { | ||
| 315 | int result; | ||
| 316 | |||
| 317 | result = acpi_bus_register_driver(&acpi_smb_hc_driver); | ||
| 318 | if (result < 0) | ||
| 319 | return -ENODEV; | ||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | static void __exit acpi_smb_hc_exit(void) | ||
| 324 | { | ||
| 325 | acpi_bus_unregister_driver(&acpi_smb_hc_driver); | ||
| 326 | } | ||
| 327 | |||
| 328 | module_init(acpi_smb_hc_init); | ||
| 329 | module_exit(acpi_smb_hc_exit); | ||
| 330 | 314 | ||
| 331 | MODULE_LICENSE("GPL"); | 315 | MODULE_LICENSE("GPL"); |
| 332 | MODULE_AUTHOR("Alexey Starikovskiy"); | 316 | MODULE_AUTHOR("Alexey Starikovskiy"); |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d1ecca2b641a..1fcb8678665c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/signal.h> | 10 | #include <linux/signal.h> |
| 11 | #include <linux/kthread.h> | 11 | #include <linux/kthread.h> |
| 12 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
| 13 | #include <linux/nls.h> | ||
| 13 | 14 | ||
| 14 | #include <acpi/acpi_drivers.h> | 15 | #include <acpi/acpi_drivers.h> |
| 15 | 16 | ||
| @@ -232,8 +233,35 @@ end: | |||
| 232 | } | 233 | } |
| 233 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); | 234 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); |
| 234 | 235 | ||
| 236 | /* sysfs file that shows description text from the ACPI _STR method */ | ||
| 237 | static ssize_t description_show(struct device *dev, | ||
| 238 | struct device_attribute *attr, | ||
| 239 | char *buf) { | ||
| 240 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
| 241 | int result; | ||
| 242 | |||
| 243 | if (acpi_dev->pnp.str_obj == NULL) | ||
| 244 | return 0; | ||
| 245 | |||
| 246 | /* | ||
| 247 | * The _STR object contains a Unicode identifier for a device. | ||
| 248 | * We need to convert to utf-8 so it can be displayed. | ||
| 249 | */ | ||
| 250 | result = utf16s_to_utf8s( | ||
| 251 | (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer, | ||
| 252 | acpi_dev->pnp.str_obj->buffer.length, | ||
| 253 | UTF16_LITTLE_ENDIAN, buf, | ||
| 254 | PAGE_SIZE); | ||
| 255 | |||
| 256 | buf[result++] = '\n'; | ||
| 257 | |||
| 258 | return result; | ||
| 259 | } | ||
| 260 | static DEVICE_ATTR(description, 0444, description_show, NULL); | ||
| 261 | |||
| 235 | static int acpi_device_setup_files(struct acpi_device *dev) | 262 | static int acpi_device_setup_files(struct acpi_device *dev) |
| 236 | { | 263 | { |
| 264 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
| 237 | acpi_status status; | 265 | acpi_status status; |
| 238 | acpi_handle temp; | 266 | acpi_handle temp; |
| 239 | int result = 0; | 267 | int result = 0; |
| @@ -257,6 +285,21 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
| 257 | goto end; | 285 | goto end; |
| 258 | } | 286 | } |
| 259 | 287 | ||
| 288 | /* | ||
| 289 | * If device has _STR, 'description' file is created | ||
| 290 | */ | ||
| 291 | status = acpi_get_handle(dev->handle, "_STR", &temp); | ||
| 292 | if (ACPI_SUCCESS(status)) { | ||
| 293 | status = acpi_evaluate_object(dev->handle, "_STR", | ||
| 294 | NULL, &buffer); | ||
| 295 | if (ACPI_FAILURE(status)) | ||
| 296 | buffer.pointer = NULL; | ||
| 297 | dev->pnp.str_obj = buffer.pointer; | ||
| 298 | result = device_create_file(&dev->dev, &dev_attr_description); | ||
| 299 | if (result) | ||
| 300 | goto end; | ||
| 301 | } | ||
| 302 | |||
| 260 | /* | 303 | /* |
| 261 | * If device has _EJ0, 'eject' file is created that is used to trigger | 304 | * If device has _EJ0, 'eject' file is created that is used to trigger |
| 262 | * hot-removal function from userland. | 305 | * hot-removal function from userland. |
| @@ -274,8 +317,15 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
| 274 | acpi_handle temp; | 317 | acpi_handle temp; |
| 275 | 318 | ||
| 276 | /* | 319 | /* |
| 277 | * If device has _EJ0, 'eject' file is created that is used to trigger | 320 | * If device has _STR, remove 'description' file |
| 278 | * hot-removal function from userland. | 321 | */ |
| 322 | status = acpi_get_handle(dev->handle, "_STR", &temp); | ||
| 323 | if (ACPI_SUCCESS(status)) { | ||
| 324 | kfree(dev->pnp.str_obj); | ||
| 325 | device_remove_file(&dev->dev, &dev_attr_description); | ||
| 326 | } | ||
| 327 | /* | ||
| 328 | * If device has _EJ0, remove 'eject' file. | ||
| 279 | */ | 329 | */ |
| 280 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); | 330 | status = acpi_get_handle(dev->handle, "_EJ0", &temp); |
| 281 | if (ACPI_SUCCESS(status)) | 331 | if (ACPI_SUCCESS(status)) |
| @@ -481,6 +531,8 @@ static int acpi_device_register(struct acpi_device *device) | |||
| 481 | INIT_LIST_HEAD(&device->children); | 531 | INIT_LIST_HEAD(&device->children); |
| 482 | INIT_LIST_HEAD(&device->node); | 532 | INIT_LIST_HEAD(&device->node); |
| 483 | INIT_LIST_HEAD(&device->wakeup_list); | 533 | INIT_LIST_HEAD(&device->wakeup_list); |
| 534 | INIT_LIST_HEAD(&device->physical_node_list); | ||
| 535 | mutex_init(&device->physical_node_lock); | ||
| 484 | 536 | ||
| 485 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); | 537 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
| 486 | if (!new_bus_id) { | 538 | if (!new_bus_id) { |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index f336bca7c450..2572d9715bda 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
| @@ -240,10 +240,17 @@ acpi_table_parse_entries(char *id, | |||
| 240 | table_end) { | 240 | table_end) { |
| 241 | if (entry->type == entry_id | 241 | if (entry->type == entry_id |
| 242 | && (!max_entries || count++ < max_entries)) | 242 | && (!max_entries || count++ < max_entries)) |
| 243 | if (handler(entry, table_end)) { | 243 | if (handler(entry, table_end)) |
| 244 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | 244 | goto err; |
| 245 | return -EINVAL; | 245 | |
| 246 | } | 246 | /* |
| 247 | * If entry->length is 0, break from this loop to avoid | ||
| 248 | * infinite loop. | ||
| 249 | */ | ||
| 250 | if (entry->length == 0) { | ||
| 251 | pr_err(PREFIX "[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); | ||
| 252 | goto err; | ||
| 253 | } | ||
| 247 | 254 | ||
| 248 | entry = (struct acpi_subtable_header *) | 255 | entry = (struct acpi_subtable_header *) |
| 249 | ((unsigned long)entry + entry->length); | 256 | ((unsigned long)entry + entry->length); |
| @@ -255,6 +262,9 @@ acpi_table_parse_entries(char *id, | |||
| 255 | 262 | ||
| 256 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | 263 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); |
| 257 | return count; | 264 | return count; |
| 265 | err: | ||
| 266 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | ||
| 267 | return -EINVAL; | ||
| 258 | } | 268 | } |
| 259 | 269 | ||
| 260 | int __init | 270 | int __init |
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 3e87c9c538aa..462f7e300363 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
| @@ -384,7 +384,7 @@ acpi_evaluate_reference(acpi_handle handle, | |||
| 384 | EXPORT_SYMBOL(acpi_evaluate_reference); | 384 | EXPORT_SYMBOL(acpi_evaluate_reference); |
| 385 | 385 | ||
| 386 | acpi_status | 386 | acpi_status |
| 387 | acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld) | 387 | acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld) |
| 388 | { | 388 | { |
| 389 | acpi_status status; | 389 | acpi_status status; |
| 390 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 390 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -400,13 +400,16 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld) | |||
| 400 | if (!output || output->type != ACPI_TYPE_PACKAGE | 400 | if (!output || output->type != ACPI_TYPE_PACKAGE |
| 401 | || !output->package.count | 401 | || !output->package.count |
| 402 | || output->package.elements[0].type != ACPI_TYPE_BUFFER | 402 | || output->package.elements[0].type != ACPI_TYPE_BUFFER |
| 403 | || output->package.elements[0].buffer.length > sizeof(*pld)) { | 403 | || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) { |
| 404 | status = AE_TYPE; | 404 | status = AE_TYPE; |
| 405 | goto out; | 405 | goto out; |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | memcpy(pld, output->package.elements[0].buffer.pointer, | 408 | status = acpi_decode_pld_buffer( |
| 409 | output->package.elements[0].buffer.length); | 409 | output->package.elements[0].buffer.pointer, |
| 410 | output->package.elements[0].buffer.length, | ||
| 411 | pld); | ||
| 412 | |||
| 410 | out: | 413 | out: |
| 411 | kfree(buffer.pointer); | 414 | kfree(buffer.pointer); |
| 412 | return status; | 415 | return status; |
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 388cbdc96db7..6aafa3d88ff0 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c | |||
| @@ -426,19 +426,7 @@ static struct acpi_driver acpi_smbus_cmi_driver = { | |||
| 426 | .remove = acpi_smbus_cmi_remove, | 426 | .remove = acpi_smbus_cmi_remove, |
| 427 | }, | 427 | }, |
| 428 | }; | 428 | }; |
| 429 | 429 | module_acpi_driver(acpi_smbus_cmi_driver); | |
| 430 | static int __init acpi_smbus_cmi_init(void) | ||
| 431 | { | ||
| 432 | return acpi_bus_register_driver(&acpi_smbus_cmi_driver); | ||
| 433 | } | ||
| 434 | |||
| 435 | static void __exit acpi_smbus_cmi_exit(void) | ||
| 436 | { | ||
| 437 | acpi_bus_unregister_driver(&acpi_smbus_cmi_driver); | ||
| 438 | } | ||
| 439 | |||
| 440 | module_init(acpi_smbus_cmi_init); | ||
| 441 | module_exit(acpi_smbus_cmi_exit); | ||
| 442 | 430 | ||
| 443 | MODULE_LICENSE("GPL"); | 431 | MODULE_LICENSE("GPL"); |
| 444 | MODULE_AUTHOR("Crane Cai <crane.cai@amd.com>"); | 432 | MODULE_AUTHOR("Crane Cai <crane.cai@amd.com>"); |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index e8726177d103..b0f6b4c8ee14 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
| @@ -413,6 +413,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { | |||
| 413 | ICPU(0x2a, idle_cpu_snb), | 413 | ICPU(0x2a, idle_cpu_snb), |
| 414 | ICPU(0x2d, idle_cpu_snb), | 414 | ICPU(0x2d, idle_cpu_snb), |
| 415 | ICPU(0x3a, idle_cpu_ivb), | 415 | ICPU(0x3a, idle_cpu_ivb), |
| 416 | ICPU(0x3e, idle_cpu_ivb), | ||
| 416 | {} | 417 | {} |
| 417 | }; | 418 | }; |
| 418 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); | 419 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); |
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 601f7372f9c4..26f13131639a 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c | |||
| @@ -151,22 +151,7 @@ static struct acpi_driver atlas_acpi_driver = { | |||
| 151 | .remove = atlas_acpi_button_remove, | 151 | .remove = atlas_acpi_button_remove, |
| 152 | }, | 152 | }, |
| 153 | }; | 153 | }; |
| 154 | 154 | module_acpi_driver(atlas_acpi_driver); | |
| 155 | static int __init atlas_acpi_init(void) | ||
| 156 | { | ||
| 157 | if (acpi_disabled) | ||
| 158 | return -ENODEV; | ||
| 159 | |||
| 160 | return acpi_bus_register_driver(&atlas_acpi_driver); | ||
| 161 | } | ||
| 162 | |||
| 163 | static void __exit atlas_acpi_exit(void) | ||
| 164 | { | ||
| 165 | acpi_bus_unregister_driver(&atlas_acpi_driver); | ||
| 166 | } | ||
| 167 | |||
| 168 | module_init(atlas_acpi_init); | ||
| 169 | module_exit(atlas_acpi_exit); | ||
| 170 | 155 | ||
| 171 | MODULE_AUTHOR("Jaya Kumar"); | 156 | MODULE_AUTHOR("Jaya Kumar"); |
| 172 | MODULE_LICENSE("GPL"); | 157 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 6b9af989632b..18d74f29dcb2 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c | |||
| @@ -382,31 +382,8 @@ static struct acpi_driver lis3lv02d_driver = { | |||
| 382 | }, | 382 | }, |
| 383 | .drv.pm = HP_ACCEL_PM, | 383 | .drv.pm = HP_ACCEL_PM, |
| 384 | }; | 384 | }; |
| 385 | 385 | module_acpi_driver(lis3lv02d_driver); | |
| 386 | static int __init lis3lv02d_init_module(void) | ||
| 387 | { | ||
| 388 | int ret; | ||
| 389 | |||
| 390 | if (acpi_disabled) | ||
| 391 | return -ENODEV; | ||
| 392 | |||
| 393 | ret = acpi_bus_register_driver(&lis3lv02d_driver); | ||
| 394 | if (ret < 0) | ||
| 395 | return ret; | ||
| 396 | |||
| 397 | pr_info("driver loaded\n"); | ||
| 398 | |||
| 399 | return 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | static void __exit lis3lv02d_exit_module(void) | ||
| 403 | { | ||
| 404 | acpi_bus_unregister_driver(&lis3lv02d_driver); | ||
| 405 | } | ||
| 406 | 386 | ||
| 407 | MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED."); | 387 | MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED."); |
| 408 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); | 388 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); |
| 409 | MODULE_LICENSE("GPL"); | 389 | MODULE_LICENSE("GPL"); |
| 410 | |||
| 411 | module_init(lis3lv02d_init_module); | ||
| 412 | module_exit(lis3lv02d_exit_module); | ||
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index dae7abe1d711..5ff4f2e314d2 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
| @@ -917,20 +917,8 @@ static struct acpi_driver ideapad_acpi_driver = { | |||
| 917 | .drv.pm = &ideapad_pm, | 917 | .drv.pm = &ideapad_pm, |
| 918 | .owner = THIS_MODULE, | 918 | .owner = THIS_MODULE, |
| 919 | }; | 919 | }; |
| 920 | 920 | module_acpi_driver(ideapad_acpi_driver); | |
| 921 | static int __init ideapad_acpi_module_init(void) | ||
| 922 | { | ||
| 923 | return acpi_bus_register_driver(&ideapad_acpi_driver); | ||
| 924 | } | ||
| 925 | |||
| 926 | static void __exit ideapad_acpi_module_exit(void) | ||
| 927 | { | ||
| 928 | acpi_bus_unregister_driver(&ideapad_acpi_driver); | ||
| 929 | } | ||
| 930 | 921 | ||
| 931 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 922 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
| 932 | MODULE_DESCRIPTION("IdeaPad ACPI Extras"); | 923 | MODULE_DESCRIPTION("IdeaPad ACPI Extras"); |
| 933 | MODULE_LICENSE("GPL"); | 924 | MODULE_LICENSE("GPL"); |
| 934 | |||
| 935 | module_init(ideapad_acpi_module_init); | ||
| 936 | module_exit(ideapad_acpi_module_exit); | ||
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index d528daa0e81c..d727bfee89a6 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c | |||
| @@ -186,27 +186,7 @@ static struct acpi_driver acpi_topstar_driver = { | |||
| 186 | .notify = acpi_topstar_notify, | 186 | .notify = acpi_topstar_notify, |
| 187 | }, | 187 | }, |
| 188 | }; | 188 | }; |
| 189 | 189 | module_acpi_driver(acpi_topstar_driver); | |
| 190 | static int __init topstar_laptop_init(void) | ||
| 191 | { | ||
| 192 | int ret; | ||
| 193 | |||
| 194 | ret = acpi_bus_register_driver(&acpi_topstar_driver); | ||
| 195 | if (ret < 0) | ||
| 196 | return ret; | ||
| 197 | |||
| 198 | pr_info("ACPI extras driver loaded\n"); | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | static void __exit topstar_laptop_exit(void) | ||
| 204 | { | ||
| 205 | acpi_bus_unregister_driver(&acpi_topstar_driver); | ||
| 206 | } | ||
| 207 | |||
| 208 | module_init(topstar_laptop_init); | ||
| 209 | module_exit(topstar_laptop_exit); | ||
| 210 | 190 | ||
| 211 | MODULE_AUTHOR("Herton Ronaldo Krzesinski"); | 191 | MODULE_AUTHOR("Herton Ronaldo Krzesinski"); |
| 212 | MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); | 192 | MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); |
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index 5e5d6317d690..e95be0b74859 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c | |||
| @@ -122,30 +122,10 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device) | |||
| 122 | return result; | 122 | return result; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static int __init toshiba_bt_rfkill_init(void) | ||
| 126 | { | ||
| 127 | int result; | ||
| 128 | |||
| 129 | result = acpi_bus_register_driver(&toshiba_bt_rfkill_driver); | ||
| 130 | if (result < 0) { | ||
| 131 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 132 | "Error registering driver\n")); | ||
| 133 | return result; | ||
| 134 | } | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type) | 125 | static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type) |
| 140 | { | 126 | { |
| 141 | /* clean up */ | 127 | /* clean up */ |
| 142 | return 0; | 128 | return 0; |
| 143 | } | 129 | } |
| 144 | 130 | ||
| 145 | static void __exit toshiba_bt_rfkill_exit(void) | 131 | module_acpi_driver(toshiba_bt_rfkill_driver); |
| 146 | { | ||
| 147 | acpi_bus_unregister_driver(&toshiba_bt_rfkill_driver); | ||
| 148 | } | ||
| 149 | |||
| 150 | module_init(toshiba_bt_rfkill_init); | ||
| 151 | module_exit(toshiba_bt_rfkill_exit); | ||
diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index 38ba39d7ca7d..16d340c3b852 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c | |||
| @@ -170,16 +170,4 @@ static struct acpi_driver xo15_ebook_driver = { | |||
| 170 | }, | 170 | }, |
| 171 | .drv.pm = &ebook_switch_pm, | 171 | .drv.pm = &ebook_switch_pm, |
| 172 | }; | 172 | }; |
| 173 | 173 | module_acpi_driver(xo15_ebook_driver); | |
| 174 | static int __init xo15_ebook_init(void) | ||
| 175 | { | ||
| 176 | return acpi_bus_register_driver(&xo15_ebook_driver); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void __exit xo15_ebook_exit(void) | ||
| 180 | { | ||
| 181 | acpi_bus_unregister_driver(&xo15_ebook_driver); | ||
| 182 | } | ||
| 183 | |||
| 184 | module_init(xo15_ebook_init); | ||
| 185 | module_exit(xo15_ebook_exit); | ||
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 507a8e2b9a4c..26b5d4b18dd7 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
| @@ -321,14 +321,9 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp) | |||
| 321 | { | 321 | { |
| 322 | struct acpi_device *acpi = to_acpi_device(dev); | 322 | struct acpi_device *acpi = to_acpi_device(dev); |
| 323 | struct pnp_dev *pnp = _pnp; | 323 | struct pnp_dev *pnp = _pnp; |
| 324 | struct device *physical_device; | ||
| 325 | |||
| 326 | physical_device = acpi_get_physical_device(acpi->handle); | ||
| 327 | if (physical_device) | ||
| 328 | put_device(physical_device); | ||
| 329 | 324 | ||
| 330 | /* true means it matched */ | 325 | /* true means it matched */ |
| 331 | return !physical_device | 326 | return !acpi->physical_node_count |
| 332 | && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); | 327 | && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); |
| 333 | } | 328 | } |
| 334 | 329 | ||
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 0ef7d42d8abe..cef4252bb31a 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c | |||
| @@ -87,7 +87,7 @@ static int usb_acpi_check_port_connect_type(struct usb_device *hdev, | |||
| 87 | acpi_status status; | 87 | acpi_status status; |
| 88 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 88 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 89 | union acpi_object *upc; | 89 | union acpi_object *upc; |
| 90 | struct acpi_pld pld; | 90 | struct acpi_pld_info *pld; |
| 91 | int ret = 0; | 91 | int ret = 0; |
| 92 | 92 | ||
| 93 | /* | 93 | /* |
| @@ -111,16 +111,17 @@ static int usb_acpi_check_port_connect_type(struct usb_device *hdev, | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | if (upc->package.elements[0].integer.value) | 113 | if (upc->package.elements[0].integer.value) |
| 114 | if (pld.user_visible) | 114 | if (pld->user_visible) |
| 115 | usb_set_hub_port_connect_type(hdev, port1, | 115 | usb_set_hub_port_connect_type(hdev, port1, |
| 116 | USB_PORT_CONNECT_TYPE_HOT_PLUG); | 116 | USB_PORT_CONNECT_TYPE_HOT_PLUG); |
| 117 | else | 117 | else |
| 118 | usb_set_hub_port_connect_type(hdev, port1, | 118 | usb_set_hub_port_connect_type(hdev, port1, |
| 119 | USB_PORT_CONNECT_TYPE_HARD_WIRED); | 119 | USB_PORT_CONNECT_TYPE_HARD_WIRED); |
| 120 | else if (!pld.user_visible) | 120 | else if (!pld->user_visible) |
| 121 | usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED); | 121 | usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED); |
| 122 | 122 | ||
| 123 | out: | 123 | out: |
| 124 | ACPI_FREE(pld); | ||
| 124 | kfree(upc); | 125 | kfree(upc); |
| 125 | return ret; | 126 | return ret; |
| 126 | } | 127 | } |
diff --git a/include/acpi/acbuffer.h b/include/acpi/acbuffer.h new file mode 100644 index 000000000000..a1e45cdd729a --- /dev/null +++ b/include/acpi/acbuffer.h | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * Name: acbuffer.h - Support for buffers returned by ACPI predefined names | ||
| 4 | * | ||
| 5 | *****************************************************************************/ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * Copyright (C) 2000 - 2012, 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 | #ifndef __ACBUFFER_H__ | ||
| 45 | #define __ACBUFFER_H__ | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Contains buffer structures for these predefined names: | ||
| 49 | * _FDE, _GRT, _GTM, _PLD, _SRT | ||
| 50 | */ | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Note: C bitfields are not used for this reason: | ||
| 54 | * | ||
| 55 | * "Bitfields are great and easy to read, but unfortunately the C language | ||
| 56 | * does not specify the layout of bitfields in memory, which means they are | ||
| 57 | * essentially useless for dealing with packed data in on-disk formats or | ||
| 58 | * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, | ||
| 59 | * this decision was a design error in C. Ritchie could have picked an order | ||
| 60 | * and stuck with it." Norman Ramsey. | ||
| 61 | * See http://stackoverflow.com/a/1053662/41661 | ||
| 62 | */ | ||
| 63 | |||
| 64 | /* _FDE return value */ | ||
| 65 | |||
| 66 | struct acpi_fde_info { | ||
| 67 | u32 floppy0; | ||
| 68 | u32 floppy1; | ||
| 69 | u32 floppy2; | ||
| 70 | u32 floppy3; | ||
| 71 | u32 tape; | ||
| 72 | }; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * _GRT return value | ||
| 76 | * _SRT input value | ||
| 77 | */ | ||
| 78 | struct acpi_grt_info { | ||
| 79 | u16 year; | ||
| 80 | u8 month; | ||
| 81 | u8 day; | ||
| 82 | u8 hour; | ||
| 83 | u8 minute; | ||
| 84 | u8 second; | ||
| 85 | u8 valid; | ||
| 86 | u16 milliseconds; | ||
| 87 | u16 timezone; | ||
| 88 | u8 daylight; | ||
| 89 | u8 reserved[3]; | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* _GTM return value */ | ||
| 93 | |||
| 94 | struct acpi_gtm_info { | ||
| 95 | u32 pio_speed0; | ||
| 96 | u32 dma_speed0; | ||
| 97 | u32 pio_speed1; | ||
| 98 | u32 dma_speed1; | ||
| 99 | u32 flags; | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Formatted _PLD return value. The minimum size is a package containing | ||
| 104 | * one buffer. | ||
| 105 | * Revision 1: Buffer is 16 bytes (128 bits) | ||
| 106 | * Revision 2: Buffer is 20 bytes (160 bits) | ||
| 107 | * | ||
| 108 | * Note: This structure is returned from the acpi_decode_pld_buffer | ||
| 109 | * interface. | ||
| 110 | */ | ||
| 111 | struct acpi_pld_info { | ||
| 112 | u8 revision; | ||
| 113 | u8 ignore_color; | ||
| 114 | u32 color; | ||
| 115 | u16 width; | ||
| 116 | u16 height; | ||
| 117 | u8 user_visible; | ||
| 118 | u8 dock; | ||
| 119 | u8 lid; | ||
| 120 | u8 panel; | ||
| 121 | u8 vertical_position; | ||
| 122 | u8 horizontal_position; | ||
| 123 | u8 shape; | ||
| 124 | u8 group_orientation; | ||
| 125 | u8 group_token; | ||
| 126 | u8 group_position; | ||
| 127 | u8 bay; | ||
| 128 | u8 ejectable; | ||
| 129 | u8 ospm_eject_required; | ||
| 130 | u8 cabinet_number; | ||
| 131 | u8 card_cage_number; | ||
| 132 | u8 reference; | ||
| 133 | u8 rotation; | ||
| 134 | u8 order; | ||
| 135 | u8 reserved; | ||
| 136 | u16 vertical_offset; | ||
| 137 | u16 horizontal_offset; | ||
| 138 | }; | ||
| 139 | |||
| 140 | /* | ||
| 141 | * Macros to: | ||
| 142 | * 1) Convert a _PLD buffer to internal struct acpi_pld_info format - ACPI_PLD_GET* | ||
| 143 | * (Used by acpi_decode_pld_buffer) | ||
| 144 | * 2) Construct a _PLD buffer - ACPI_PLD_SET* | ||
| 145 | * (Intended for BIOS use only) | ||
| 146 | */ | ||
| 147 | #define ACPI_PLD_REV1_BUFFER_SIZE 16 /* For Revision 1 of the buffer (From ACPI spec) */ | ||
| 148 | #define ACPI_PLD_BUFFER_SIZE 20 /* For Revision 2 of the buffer (From ACPI spec) */ | ||
| 149 | |||
| 150 | /* First 32-bit dword, bits 0:32 */ | ||
| 151 | |||
| 152 | #define ACPI_PLD_GET_REVISION(dword) ACPI_GET_BITS (dword, 0, ACPI_7BIT_MASK) | ||
| 153 | #define ACPI_PLD_SET_REVISION(dword,value) ACPI_SET_BITS (dword, 0, ACPI_7BIT_MASK, value) /* Offset 0, Len 7 */ | ||
| 154 | |||
| 155 | #define ACPI_PLD_GET_IGNORE_COLOR(dword) ACPI_GET_BITS (dword, 7, ACPI_1BIT_MASK) | ||
| 156 | #define ACPI_PLD_SET_IGNORE_COLOR(dword,value) ACPI_SET_BITS (dword, 7, ACPI_1BIT_MASK, value) /* Offset 7, Len 1 */ | ||
| 157 | |||
| 158 | #define ACPI_PLD_GET_COLOR(dword) ACPI_GET_BITS (dword, 8, ACPI_24BIT_MASK) | ||
| 159 | #define ACPI_PLD_SET_COLOR(dword,value) ACPI_SET_BITS (dword, 8, ACPI_24BIT_MASK, value) /* Offset 8, Len 24 */ | ||
| 160 | |||
| 161 | /* Second 32-bit dword, bits 33:63 */ | ||
| 162 | |||
| 163 | #define ACPI_PLD_GET_WIDTH(dword) ACPI_GET_BITS (dword, 0, ACPI_16BIT_MASK) | ||
| 164 | #define ACPI_PLD_SET_WIDTH(dword,value) ACPI_SET_BITS (dword, 0, ACPI_16BIT_MASK, value) /* Offset 32+0=32, Len 16 */ | ||
| 165 | |||
| 166 | #define ACPI_PLD_GET_HEIGHT(dword) ACPI_GET_BITS (dword, 16, ACPI_16BIT_MASK) | ||
| 167 | #define ACPI_PLD_SET_HEIGHT(dword,value) ACPI_SET_BITS (dword, 16, ACPI_16BIT_MASK, value) /* Offset 32+16=48, Len 16 */ | ||
| 168 | |||
| 169 | /* Third 32-bit dword, bits 64:95 */ | ||
| 170 | |||
| 171 | #define ACPI_PLD_GET_USER_VISIBLE(dword) ACPI_GET_BITS (dword, 0, ACPI_1BIT_MASK) | ||
| 172 | #define ACPI_PLD_SET_USER_VISIBLE(dword,value) ACPI_SET_BITS (dword, 0, ACPI_1BIT_MASK, value) /* Offset 64+0=64, Len 1 */ | ||
| 173 | |||
| 174 | #define ACPI_PLD_GET_DOCK(dword) ACPI_GET_BITS (dword, 1, ACPI_1BIT_MASK) | ||
| 175 | #define ACPI_PLD_SET_DOCK(dword,value) ACPI_SET_BITS (dword, 1, ACPI_1BIT_MASK, value) /* Offset 64+1=65, Len 1 */ | ||
| 176 | |||
| 177 | #define ACPI_PLD_GET_LID(dword) ACPI_GET_BITS (dword, 2, ACPI_1BIT_MASK) | ||
| 178 | #define ACPI_PLD_SET_LID(dword,value) ACPI_SET_BITS (dword, 2, ACPI_1BIT_MASK, value) /* Offset 64+2=66, Len 1 */ | ||
| 179 | |||
| 180 | #define ACPI_PLD_GET_PANEL(dword) ACPI_GET_BITS (dword, 3, ACPI_3BIT_MASK) | ||
| 181 | #define ACPI_PLD_SET_PANEL(dword,value) ACPI_SET_BITS (dword, 3, ACPI_3BIT_MASK, value) /* Offset 64+3=67, Len 3 */ | ||
| 182 | |||
| 183 | #define ACPI_PLD_GET_VERTICAL(dword) ACPI_GET_BITS (dword, 6, ACPI_2BIT_MASK) | ||
| 184 | #define ACPI_PLD_SET_VERTICAL(dword,value) ACPI_SET_BITS (dword, 6, ACPI_2BIT_MASK, value) /* Offset 64+6=70, Len 2 */ | ||
| 185 | |||
| 186 | #define ACPI_PLD_GET_HORIZONTAL(dword) ACPI_GET_BITS (dword, 8, ACPI_2BIT_MASK) | ||
| 187 | #define ACPI_PLD_SET_HORIZONTAL(dword,value) ACPI_SET_BITS (dword, 8, ACPI_2BIT_MASK, value) /* Offset 64+8=72, Len 2 */ | ||
| 188 | |||
| 189 | #define ACPI_PLD_GET_SHAPE(dword) ACPI_GET_BITS (dword, 10, ACPI_4BIT_MASK) | ||
| 190 | #define ACPI_PLD_SET_SHAPE(dword,value) ACPI_SET_BITS (dword, 10, ACPI_4BIT_MASK, value) /* Offset 64+10=74, Len 4 */ | ||
| 191 | |||
| 192 | #define ACPI_PLD_GET_ORIENTATION(dword) ACPI_GET_BITS (dword, 14, ACPI_1BIT_MASK) | ||
| 193 | #define ACPI_PLD_SET_ORIENTATION(dword,value) ACPI_SET_BITS (dword, 14, ACPI_1BIT_MASK, value) /* Offset 64+14=78, Len 1 */ | ||
| 194 | |||
| 195 | #define ACPI_PLD_GET_TOKEN(dword) ACPI_GET_BITS (dword, 15, ACPI_8BIT_MASK) | ||
| 196 | #define ACPI_PLD_SET_TOKEN(dword,value) ACPI_SET_BITS (dword, 15, ACPI_8BIT_MASK, value) /* Offset 64+15=79, Len 8 */ | ||
| 197 | |||
| 198 | #define ACPI_PLD_GET_POSITION(dword) ACPI_GET_BITS (dword, 23, ACPI_8BIT_MASK) | ||
| 199 | #define ACPI_PLD_SET_POSITION(dword,value) ACPI_SET_BITS (dword, 23, ACPI_8BIT_MASK, value) /* Offset 64+23=87, Len 8 */ | ||
| 200 | |||
| 201 | #define ACPI_PLD_GET_BAY(dword) ACPI_GET_BITS (dword, 31, ACPI_1BIT_MASK) | ||
| 202 | #define ACPI_PLD_SET_BAY(dword,value) ACPI_SET_BITS (dword, 31, ACPI_1BIT_MASK, value) /* Offset 64+31=95, Len 1 */ | ||
| 203 | |||
| 204 | /* Fourth 32-bit dword, bits 96:127 */ | ||
| 205 | |||
| 206 | #define ACPI_PLD_GET_EJECTABLE(dword) ACPI_GET_BITS (dword, 0, ACPI_1BIT_MASK) | ||
| 207 | #define ACPI_PLD_SET_EJECTABLE(dword,value) ACPI_SET_BITS (dword, 0, ACPI_1BIT_MASK, value) /* Offset 96+0=96, Len 1 */ | ||
| 208 | |||
| 209 | #define ACPI_PLD_GET_OSPM_EJECT(dword) ACPI_GET_BITS (dword, 1, ACPI_1BIT_MASK) | ||
| 210 | #define ACPI_PLD_SET_OSPM_EJECT(dword,value) ACPI_SET_BITS (dword, 1, ACPI_1BIT_MASK, value) /* Offset 96+1=97, Len 1 */ | ||
| 211 | |||
| 212 | #define ACPI_PLD_GET_CABINET(dword) ACPI_GET_BITS (dword, 2, ACPI_8BIT_MASK) | ||
| 213 | #define ACPI_PLD_SET_CABINET(dword,value) ACPI_SET_BITS (dword, 2, ACPI_8BIT_MASK, value) /* Offset 96+2=98, Len 8 */ | ||
| 214 | |||
| 215 | #define ACPI_PLD_GET_CARD_CAGE(dword) ACPI_GET_BITS (dword, 10, ACPI_8BIT_MASK) | ||
| 216 | #define ACPI_PLD_SET_CARD_CAGE(dword,value) ACPI_SET_BITS (dword, 10, ACPI_8BIT_MASK, value) /* Offset 96+10=106, Len 8 */ | ||
| 217 | |||
| 218 | #define ACPI_PLD_GET_REFERENCE(dword) ACPI_GET_BITS (dword, 18, ACPI_1BIT_MASK) | ||
| 219 | #define ACPI_PLD_SET_REFERENCE(dword,value) ACPI_SET_BITS (dword, 18, ACPI_1BIT_MASK, value) /* Offset 96+18=114, Len 1 */ | ||
| 220 | |||
| 221 | #define ACPI_PLD_GET_ROTATION(dword) ACPI_GET_BITS (dword, 19, ACPI_4BIT_MASK) | ||
| 222 | #define ACPI_PLD_SET_ROTATION(dword,value) ACPI_SET_BITS (dword, 19, ACPI_4BIT_MASK, value) /* Offset 96+19=115, Len 4 */ | ||
| 223 | |||
| 224 | #define ACPI_PLD_GET_ORDER(dword) ACPI_GET_BITS (dword, 23, ACPI_5BIT_MASK) | ||
| 225 | #define ACPI_PLD_SET_ORDER(dword,value) ACPI_SET_BITS (dword, 23, ACPI_5BIT_MASK, value) /* Offset 96+23=119, Len 5 */ | ||
| 226 | |||
| 227 | /* Fifth 32-bit dword, bits 128:159 (Revision 2 of _PLD only) */ | ||
| 228 | |||
| 229 | #define ACPI_PLD_GET_VERT_OFFSET(dword) ACPI_GET_BITS (dword, 0, ACPI_16BIT_MASK) | ||
| 230 | #define ACPI_PLD_SET_VERT_OFFSET(dword,value) ACPI_SET_BITS (dword, 0, ACPI_16BIT_MASK, value) /* Offset 128+0=128, Len 16 */ | ||
| 231 | |||
| 232 | #define ACPI_PLD_GET_HORIZ_OFFSET(dword) ACPI_GET_BITS (dword, 16, ACPI_16BIT_MASK) | ||
| 233 | #define ACPI_PLD_SET_HORIZ_OFFSET(dword,value) ACPI_SET_BITS (dword, 16, ACPI_16BIT_MASK, value) /* Offset 128+16=144, Len 16 */ | ||
| 234 | |||
| 235 | #endif /* ACBUFFER_H */ | ||
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index d988ac54f41e..745dd24e3cb5 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h | |||
| @@ -63,11 +63,10 @@ | |||
| 63 | #define METHOD_NAME__PRW "_PRW" | 63 | #define METHOD_NAME__PRW "_PRW" |
| 64 | #define METHOD_NAME__SRS "_SRS" | 64 | #define METHOD_NAME__SRS "_SRS" |
| 65 | #define METHOD_NAME__CBA "_CBA" | 65 | #define METHOD_NAME__CBA "_CBA" |
| 66 | #define METHOD_NAME__PLD "_PLD" | ||
| 66 | 67 | ||
| 67 | /* Method names - these methods must appear at the namespace root */ | 68 | /* Method names - these methods must appear at the namespace root */ |
| 68 | 69 | ||
| 69 | #define METHOD_PATHNAME__BFS "\\_BFS" | ||
| 70 | #define METHOD_PATHNAME__GTS "\\_GTS" | ||
| 71 | #define METHOD_PATHNAME__PTS "\\_PTS" | 70 | #define METHOD_PATHNAME__PTS "\\_PTS" |
| 72 | #define METHOD_PATHNAME__SST "\\_SI._SST" | 71 | #define METHOD_PATHNAME__SST "\\_SI._SST" |
| 73 | #define METHOD_PATHNAME__WAK "\\_WAK" | 72 | #define METHOD_PATHNAME__WAK "\\_WAK" |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index bde976ee068d..0daa0fbd8654 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -54,37 +54,8 @@ acpi_status | |||
| 54 | acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, | 54 | acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, |
| 55 | u32 status_code, struct acpi_buffer *status_buf); | 55 | u32 status_code, struct acpi_buffer *status_buf); |
| 56 | 56 | ||
| 57 | struct acpi_pld { | ||
| 58 | unsigned int revision:7; /* 0 */ | ||
| 59 | unsigned int ignore_colour:1; /* 7 */ | ||
| 60 | unsigned int colour:24; /* 8 */ | ||
| 61 | unsigned int width:16; /* 32 */ | ||
| 62 | unsigned int height:16; /* 48 */ | ||
| 63 | unsigned int user_visible:1; /* 64 */ | ||
| 64 | unsigned int dock:1; /* 65 */ | ||
| 65 | unsigned int lid:1; /* 66 */ | ||
| 66 | unsigned int panel:3; /* 67 */ | ||
| 67 | unsigned int vertical_pos:2; /* 70 */ | ||
| 68 | unsigned int horizontal_pos:2; /* 72 */ | ||
| 69 | unsigned int shape:4; /* 74 */ | ||
| 70 | unsigned int group_orientation:1; /* 78 */ | ||
| 71 | unsigned int group_token:8; /* 79 */ | ||
| 72 | unsigned int group_position:8; /* 87 */ | ||
| 73 | unsigned int bay:1; /* 95 */ | ||
| 74 | unsigned int ejectable:1; /* 96 */ | ||
| 75 | unsigned int ospm_eject_required:1; /* 97 */ | ||
| 76 | unsigned int cabinet_number:8; /* 98 */ | ||
| 77 | unsigned int card_cage_number:8; /* 106 */ | ||
| 78 | unsigned int reference:1; /* 114 */ | ||
| 79 | unsigned int rotation:4; /* 115 */ | ||
| 80 | unsigned int order:5; /* 119 */ | ||
| 81 | unsigned int reserved:4; /* 124 */ | ||
| 82 | unsigned int vertical_offset:16; /* 128 */ | ||
| 83 | unsigned int horizontal_offset:16; /* 144 */ | ||
| 84 | } __attribute__((__packed__)); | ||
| 85 | |||
| 86 | acpi_status | 57 | acpi_status |
| 87 | acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld); | 58 | acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld); |
| 88 | #ifdef CONFIG_ACPI | 59 | #ifdef CONFIG_ACPI |
| 89 | 60 | ||
| 90 | #include <linux/proc_fs.h> | 61 | #include <linux/proc_fs.h> |
| @@ -208,6 +179,7 @@ struct acpi_device_pnp { | |||
| 208 | struct list_head ids; /* _HID and _CIDs */ | 179 | struct list_head ids; /* _HID and _CIDs */ |
| 209 | acpi_device_name device_name; /* Driver-determined */ | 180 | acpi_device_name device_name; /* Driver-determined */ |
| 210 | acpi_device_class device_class; /* " */ | 181 | acpi_device_class device_class; /* " */ |
| 182 | union acpi_object *str_obj; /* unicode string for _STR method */ | ||
| 211 | }; | 183 | }; |
| 212 | 184 | ||
| 213 | #define acpi_device_bid(d) ((d)->pnp.bus_id) | 185 | #define acpi_device_bid(d) ((d)->pnp.bus_id) |
| @@ -282,8 +254,16 @@ struct acpi_device_wakeup { | |||
| 282 | int prepare_count; | 254 | int prepare_count; |
| 283 | }; | 255 | }; |
| 284 | 256 | ||
| 285 | /* Device */ | 257 | struct acpi_device_physical_node { |
| 258 | u8 node_id; | ||
| 259 | struct list_head node; | ||
| 260 | struct device *dev; | ||
| 261 | }; | ||
| 262 | |||
| 263 | /* set maximum of physical nodes to 32 for expansibility */ | ||
| 264 | #define ACPI_MAX_PHYSICAL_NODE 32 | ||
| 286 | 265 | ||
| 266 | /* Device */ | ||
| 287 | struct acpi_device { | 267 | struct acpi_device { |
| 288 | int device_type; | 268 | int device_type; |
| 289 | acpi_handle handle; /* no handle for fixed hardware */ | 269 | acpi_handle handle; /* no handle for fixed hardware */ |
| @@ -304,6 +284,10 @@ struct acpi_device { | |||
| 304 | struct device dev; | 284 | struct device dev; |
| 305 | struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ | 285 | struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ |
| 306 | enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ | 286 | enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ |
| 287 | u8 physical_node_count; | ||
| 288 | struct list_head physical_node_list; | ||
| 289 | struct mutex physical_node_lock; | ||
| 290 | DECLARE_BITMAP(physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE); | ||
| 307 | }; | 291 | }; |
| 308 | 292 | ||
| 309 | static inline void *acpi_driver_data(struct acpi_device *d) | 293 | static inline void *acpi_driver_data(struct acpi_device *d) |
| @@ -381,6 +365,19 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
| 381 | int acpi_create_dir(struct acpi_device *); | 365 | int acpi_create_dir(struct acpi_device *); |
| 382 | void acpi_remove_dir(struct acpi_device *); | 366 | void acpi_remove_dir(struct acpi_device *); |
| 383 | 367 | ||
| 368 | |||
| 369 | /** | ||
| 370 | * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver | ||
| 371 | * @__acpi_driver: acpi_driver struct | ||
| 372 | * | ||
| 373 | * Helper macro for ACPI drivers which do not do anything special in module | ||
| 374 | * init/exit. This eliminates a lot of boilerplate. Each module may only | ||
| 375 | * use this macro once, and calling it replaces module_init() and module_exit() | ||
| 376 | */ | ||
| 377 | #define module_acpi_driver(__acpi_driver) \ | ||
| 378 | module_driver(__acpi_driver, acpi_bus_register_driver, \ | ||
| 379 | acpi_bus_unregister_driver) | ||
| 380 | |||
| 384 | /* | 381 | /* |
| 385 | * Bind physical devices with ACPI devices | 382 | * Bind physical devices with ACPI devices |
| 386 | */ | 383 | */ |
| @@ -394,7 +391,6 @@ struct acpi_bus_type { | |||
| 394 | }; | 391 | }; |
| 395 | int register_acpi_bus_type(struct acpi_bus_type *); | 392 | int register_acpi_bus_type(struct acpi_bus_type *); |
| 396 | int unregister_acpi_bus_type(struct acpi_bus_type *); | 393 | int unregister_acpi_bus_type(struct acpi_bus_type *); |
| 397 | struct device *acpi_get_physical_device(acpi_handle); | ||
| 398 | 394 | ||
| 399 | struct acpi_pci_root { | 395 | struct acpi_pci_root { |
| 400 | struct list_head node; | 396 | struct list_head node; |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 51405d32ac64..8b891dbead66 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
| @@ -47,11 +47,12 @@ | |||
| 47 | 47 | ||
| 48 | /* Current ACPICA subsystem version in YYYYMMDD format */ | 48 | /* Current ACPICA subsystem version in YYYYMMDD format */ |
| 49 | 49 | ||
| 50 | #define ACPI_CA_VERSION 0x20120711 | 50 | #define ACPI_CA_VERSION 0x20120913 |
| 51 | 51 | ||
| 52 | #include <acpi/acconfig.h> | 52 | #include <acpi/acconfig.h> |
| 53 | #include <acpi/actypes.h> | 53 | #include <acpi/actypes.h> |
| 54 | #include <acpi/actbl.h> | 54 | #include <acpi/actbl.h> |
| 55 | #include <acpi/acbuffer.h> | ||
| 55 | 56 | ||
| 56 | extern u8 acpi_gbl_permanent_mmap; | 57 | extern u8 acpi_gbl_permanent_mmap; |
| 57 | 58 | ||
| @@ -144,6 +145,10 @@ acpi_check_address_range(acpi_adr_space_type space_id, | |||
| 144 | acpi_physical_address address, | 145 | acpi_physical_address address, |
| 145 | acpi_size length, u8 warn); | 146 | acpi_size length, u8 warn); |
| 146 | 147 | ||
| 148 | acpi_status | ||
| 149 | acpi_decode_pld_buffer(u8 *in_buffer, | ||
| 150 | acpi_size length, struct acpi_pld_info **return_buffer); | ||
| 151 | |||
| 147 | /* | 152 | /* |
| 148 | * ACPI Memory management | 153 | * ACPI Memory management |
| 149 | */ | 154 | */ |
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 59a73e1b2845..4f94b1d812d5 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h | |||
| @@ -79,9 +79,15 @@ | |||
| 79 | #pragma pack(1) | 79 | #pragma pack(1) |
| 80 | 80 | ||
| 81 | /* | 81 | /* |
| 82 | * Note about bitfields: The u8 type is used for bitfields in ACPI tables. | 82 | * Note: C bitfields are not used for this reason: |
| 83 | * This is the only type that is even remotely portable. Anything else is not | 83 | * |
| 84 | * portable, so do not use any other bitfield types. | 84 | * "Bitfields are great and easy to read, but unfortunately the C language |
| 85 | * does not specify the layout of bitfields in memory, which means they are | ||
| 86 | * essentially useless for dealing with packed data in on-disk formats or | ||
| 87 | * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, | ||
| 88 | * this decision was a design error in C. Ritchie could have picked an order | ||
| 89 | * and stuck with it." Norman Ramsey. | ||
| 90 | * See http://stackoverflow.com/a/1053662/41661 | ||
| 85 | */ | 91 | */ |
| 86 | 92 | ||
| 87 | /******************************************************************************* | 93 | /******************************************************************************* |
| @@ -94,7 +100,7 @@ | |||
| 94 | struct acpi_table_header { | 100 | struct acpi_table_header { |
| 95 | char signature[ACPI_NAME_SIZE]; /* ASCII table signature */ | 101 | char signature[ACPI_NAME_SIZE]; /* ASCII table signature */ |
| 96 | u32 length; /* Length of table in bytes, including this header */ | 102 | u32 length; /* Length of table in bytes, including this header */ |
| 97 | u8 revision; /* ACPI Specification minor version # */ | 103 | u8 revision; /* ACPI Specification minor version number */ |
| 98 | u8 checksum; /* To make sum of entire table == 0 */ | 104 | u8 checksum; /* To make sum of entire table == 0 */ |
| 99 | char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ | 105 | char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */ |
| 100 | char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ | 106 | char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */ |
| @@ -108,7 +114,7 @@ struct acpi_table_header { | |||
| 108 | * GAS - Generic Address Structure (ACPI 2.0+) | 114 | * GAS - Generic Address Structure (ACPI 2.0+) |
| 109 | * | 115 | * |
| 110 | * Note: Since this structure is used in the ACPI tables, it is byte aligned. | 116 | * Note: Since this structure is used in the ACPI tables, it is byte aligned. |
| 111 | * If misaliged access is not supported by the hardware, accesses to the | 117 | * If misaligned access is not supported by the hardware, accesses to the |
| 112 | * 64-bit Address field must be performed with care. | 118 | * 64-bit Address field must be performed with care. |
| 113 | * | 119 | * |
| 114 | ******************************************************************************/ | 120 | ******************************************************************************/ |
| @@ -210,18 +216,18 @@ struct acpi_table_fadt { | |||
| 210 | u8 preferred_profile; /* Conveys preferred power management profile to OSPM. */ | 216 | u8 preferred_profile; /* Conveys preferred power management profile to OSPM. */ |
| 211 | u16 sci_interrupt; /* System vector of SCI interrupt */ | 217 | u16 sci_interrupt; /* System vector of SCI interrupt */ |
| 212 | u32 smi_command; /* 32-bit Port address of SMI command port */ | 218 | u32 smi_command; /* 32-bit Port address of SMI command port */ |
| 213 | u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ | 219 | u8 acpi_enable; /* Value to write to SMI_CMD to enable ACPI */ |
| 214 | u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ | 220 | u8 acpi_disable; /* Value to write to SMI_CMD to disable ACPI */ |
| 215 | u8 s4_bios_request; /* Value to write to SMI CMD to enter S4BIOS state */ | 221 | u8 s4_bios_request; /* Value to write to SMI_CMD to enter S4BIOS state */ |
| 216 | u8 pstate_control; /* Processor performance state control */ | 222 | u8 pstate_control; /* Processor performance state control */ |
| 217 | u32 pm1a_event_block; /* 32-bit Port address of Power Mgt 1a Event Reg Blk */ | 223 | u32 pm1a_event_block; /* 32-bit port address of Power Mgt 1a Event Reg Blk */ |
| 218 | u32 pm1b_event_block; /* 32-bit Port address of Power Mgt 1b Event Reg Blk */ | 224 | u32 pm1b_event_block; /* 32-bit port address of Power Mgt 1b Event Reg Blk */ |
| 219 | u32 pm1a_control_block; /* 32-bit Port address of Power Mgt 1a Control Reg Blk */ | 225 | u32 pm1a_control_block; /* 32-bit port address of Power Mgt 1a Control Reg Blk */ |
| 220 | u32 pm1b_control_block; /* 32-bit Port address of Power Mgt 1b Control Reg Blk */ | 226 | u32 pm1b_control_block; /* 32-bit port address of Power Mgt 1b Control Reg Blk */ |
| 221 | u32 pm2_control_block; /* 32-bit Port address of Power Mgt 2 Control Reg Blk */ | 227 | u32 pm2_control_block; /* 32-bit port address of Power Mgt 2 Control Reg Blk */ |
| 222 | u32 pm_timer_block; /* 32-bit Port address of Power Mgt Timer Ctrl Reg Blk */ | 228 | u32 pm_timer_block; /* 32-bit port address of Power Mgt Timer Ctrl Reg Blk */ |
| 223 | u32 gpe0_block; /* 32-bit Port address of General Purpose Event 0 Reg Blk */ | 229 | u32 gpe0_block; /* 32-bit port address of General Purpose Event 0 Reg Blk */ |
| 224 | u32 gpe1_block; /* 32-bit Port address of General Purpose Event 1 Reg Blk */ | 230 | u32 gpe1_block; /* 32-bit port address of General Purpose Event 1 Reg Blk */ |
| 225 | u8 pm1_event_length; /* Byte Length of ports at pm1x_event_block */ | 231 | u8 pm1_event_length; /* Byte Length of ports at pm1x_event_block */ |
| 226 | u8 pm1_control_length; /* Byte Length of ports at pm1x_control_block */ | 232 | u8 pm1_control_length; /* Byte Length of ports at pm1x_control_block */ |
| 227 | u8 pm2_control_length; /* Byte Length of ports at pm2_control_block */ | 233 | u8 pm2_control_length; /* Byte Length of ports at pm2_control_block */ |
| @@ -229,12 +235,12 @@ struct acpi_table_fadt { | |||
| 229 | u8 gpe0_block_length; /* Byte Length of ports at gpe0_block */ | 235 | u8 gpe0_block_length; /* Byte Length of ports at gpe0_block */ |
| 230 | u8 gpe1_block_length; /* Byte Length of ports at gpe1_block */ | 236 | u8 gpe1_block_length; /* Byte Length of ports at gpe1_block */ |
| 231 | u8 gpe1_base; /* Offset in GPE number space where GPE1 events start */ | 237 | u8 gpe1_base; /* Offset in GPE number space where GPE1 events start */ |
| 232 | u8 cst_control; /* Support for the _CST object and C States change notification */ | 238 | u8 cst_control; /* Support for the _CST object and C-States change notification */ |
| 233 | u16 c2_latency; /* Worst case HW latency to enter/exit C2 state */ | 239 | u16 c2_latency; /* Worst case HW latency to enter/exit C2 state */ |
| 234 | u16 c3_latency; /* Worst case HW latency to enter/exit C3 state */ | 240 | u16 c3_latency; /* Worst case HW latency to enter/exit C3 state */ |
| 235 | u16 flush_size; /* Processor's memory cache line width, in bytes */ | 241 | u16 flush_size; /* Processor memory cache line width, in bytes */ |
| 236 | u16 flush_stride; /* Number of flush strides that need to be read */ | 242 | u16 flush_stride; /* Number of flush strides that need to be read */ |
| 237 | u8 duty_offset; /* Processor duty cycle index in processor's P_CNT reg */ | 243 | u8 duty_offset; /* Processor duty cycle index in processor P_CNT reg */ |
| 238 | u8 duty_width; /* Processor duty cycle value bit width in P_CNT register */ | 244 | u8 duty_width; /* Processor duty cycle value bit width in P_CNT register */ |
| 239 | u8 day_alarm; /* Index to day-of-month alarm in RTC CMOS RAM */ | 245 | u8 day_alarm; /* Index to day-of-month alarm in RTC CMOS RAM */ |
| 240 | u8 month_alarm; /* Index to month-of-year alarm in RTC CMOS RAM */ | 246 | u8 month_alarm; /* Index to month-of-year alarm in RTC CMOS RAM */ |
| @@ -255,11 +261,11 @@ struct acpi_table_fadt { | |||
| 255 | struct acpi_generic_address xpm_timer_block; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ | 261 | struct acpi_generic_address xpm_timer_block; /* 64-bit Extended Power Mgt Timer Ctrl Reg Blk address */ |
| 256 | struct acpi_generic_address xgpe0_block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */ | 262 | struct acpi_generic_address xgpe0_block; /* 64-bit Extended General Purpose Event 0 Reg Blk address */ |
| 257 | struct acpi_generic_address xgpe1_block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ | 263 | struct acpi_generic_address xgpe1_block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ |
| 258 | struct acpi_generic_address sleep_control; /* 64-bit Sleep Control register */ | 264 | struct acpi_generic_address sleep_control; /* 64-bit Sleep Control register (ACPI 5.0) */ |
| 259 | struct acpi_generic_address sleep_status; /* 64-bit Sleep Status register */ | 265 | struct acpi_generic_address sleep_status; /* 64-bit Sleep Status register (ACPI 5.0) */ |
| 260 | }; | 266 | }; |
| 261 | 267 | ||
| 262 | /* Masks for FADT Boot Architecture Flags (boot_flags) */ | 268 | /* Masks for FADT Boot Architecture Flags (boot_flags) [Vx]=Introduced in this FADT revision */ |
| 263 | 269 | ||
| 264 | #define ACPI_FADT_LEGACY_DEVICES (1) /* 00: [V2] System has LPC or ISA bus devices */ | 270 | #define ACPI_FADT_LEGACY_DEVICES (1) /* 00: [V2] System has LPC or ISA bus devices */ |
| 265 | #define ACPI_FADT_8042 (1<<1) /* 01: [V3] System has an 8042 controller on port 60/64 */ | 271 | #define ACPI_FADT_8042 (1<<1) /* 01: [V3] System has an 8042 controller on port 60/64 */ |
| @@ -272,13 +278,13 @@ struct acpi_table_fadt { | |||
| 272 | 278 | ||
| 273 | /* Masks for FADT flags */ | 279 | /* Masks for FADT flags */ |
| 274 | 280 | ||
| 275 | #define ACPI_FADT_WBINVD (1) /* 00: [V1] The wbinvd instruction works properly */ | 281 | #define ACPI_FADT_WBINVD (1) /* 00: [V1] The WBINVD instruction works properly */ |
| 276 | #define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: [V1] wbinvd flushes but does not invalidate caches */ | 282 | #define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: [V1] WBINVD flushes but does not invalidate caches */ |
| 277 | #define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: [V1] All processors support C1 state */ | 283 | #define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: [V1] All processors support C1 state */ |
| 278 | #define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: [V1] C2 state works on MP system */ | 284 | #define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: [V1] C2 state works on MP system */ |
| 279 | #define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: [V1] Power button is handled as a control method device */ | 285 | #define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: [V1] Power button is handled as a control method device */ |
| 280 | #define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: [V1] Sleep button is handled as a control method device */ | 286 | #define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: [V1] Sleep button is handled as a control method device */ |
| 281 | #define ACPI_FADT_FIXED_RTC (1<<6) /* 06: [V1] RTC wakeup status not in fixed register space */ | 287 | #define ACPI_FADT_FIXED_RTC (1<<6) /* 06: [V1] RTC wakeup status is not in fixed register space */ |
| 282 | #define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: [V1] RTC alarm can wake system from S4 */ | 288 | #define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: [V1] RTC alarm can wake system from S4 */ |
| 283 | #define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: [V1] ACPI timer width is 32-bit (0=24-bit) */ | 289 | #define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: [V1] ACPI timer width is 32-bit (0=24-bit) */ |
| 284 | #define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: [V1] Docking supported */ | 290 | #define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: [V1] Docking supported */ |
| @@ -297,7 +303,7 @@ struct acpi_table_fadt { | |||
| 297 | 303 | ||
| 298 | /* Values for preferred_profile (Preferred Power Management Profiles) */ | 304 | /* Values for preferred_profile (Preferred Power Management Profiles) */ |
| 299 | 305 | ||
| 300 | enum acpi_prefered_pm_profiles { | 306 | enum acpi_preferred_pm_profiles { |
| 301 | PM_UNSPECIFIED = 0, | 307 | PM_UNSPECIFIED = 0, |
| 302 | PM_DESKTOP = 1, | 308 | PM_DESKTOP = 1, |
| 303 | PM_MOBILE = 2, | 309 | PM_MOBILE = 2, |
| @@ -335,7 +341,7 @@ union acpi_name_union { | |||
| 335 | struct acpi_table_desc { | 341 | struct acpi_table_desc { |
| 336 | acpi_physical_address address; | 342 | acpi_physical_address address; |
| 337 | struct acpi_table_header *pointer; | 343 | struct acpi_table_header *pointer; |
| 338 | u32 length; /* Length fixed at 32 bits */ | 344 | u32 length; /* Length fixed at 32 bits (fixed in table header) */ |
| 339 | union acpi_name_union signature; | 345 | union acpi_name_union signature; |
| 340 | acpi_owner_id owner_id; | 346 | acpi_owner_id owner_id; |
| 341 | u8 flags; | 347 | u8 flags; |
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 300d14e7c5d5..280fc45b59dd 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h | |||
| @@ -79,9 +79,15 @@ | |||
| 79 | #pragma pack(1) | 79 | #pragma pack(1) |
| 80 | 80 | ||
| 81 | /* | 81 | /* |
| 82 | * Note about bitfields: The u8 type is used for bitfields in ACPI tables. | 82 | * Note: C bitfields are not used for this reason: |
| 83 | * This is the only type that is even remotely portable. Anything else is not | 83 | * |
| 84 | * portable, so do not use any other bitfield types. | 84 | * "Bitfields are great and easy to read, but unfortunately the C language |
| 85 | * does not specify the layout of bitfields in memory, which means they are | ||
| 86 | * essentially useless for dealing with packed data in on-disk formats or | ||
| 87 | * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, | ||
| 88 | * this decision was a design error in C. Ritchie could have picked an order | ||
| 89 | * and stuck with it." Norman Ramsey. | ||
| 90 | * See http://stackoverflow.com/a/1053662/41661 | ||
| 85 | */ | 91 | */ |
| 86 | 92 | ||
| 87 | /******************************************************************************* | 93 | /******************************************************************************* |
| @@ -489,7 +495,9 @@ enum acpi_hest_notify_types { | |||
| 489 | ACPI_HEST_NOTIFY_LOCAL = 2, | 495 | ACPI_HEST_NOTIFY_LOCAL = 2, |
| 490 | ACPI_HEST_NOTIFY_SCI = 3, | 496 | ACPI_HEST_NOTIFY_SCI = 3, |
| 491 | ACPI_HEST_NOTIFY_NMI = 4, | 497 | ACPI_HEST_NOTIFY_NMI = 4, |
| 492 | ACPI_HEST_NOTIFY_RESERVED = 5 /* 5 and greater are reserved */ | 498 | ACPI_HEST_NOTIFY_CMCI = 5, /* ACPI 5.0 */ |
| 499 | ACPI_HEST_NOTIFY_MCE = 6, /* ACPI 5.0 */ | ||
| 500 | ACPI_HEST_NOTIFY_RESERVED = 7 /* 7 and greater are reserved */ | ||
| 493 | }; | 501 | }; |
| 494 | 502 | ||
| 495 | /* Values for config_write_enable bitfield above */ | 503 | /* Values for config_write_enable bitfield above */ |
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index d9ceb3d31629..1b2b356486d1 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h | |||
| @@ -63,6 +63,8 @@ | |||
| 63 | */ | 63 | */ |
| 64 | #define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ | 64 | #define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ |
| 65 | #define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ | 65 | #define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ |
| 66 | #define ACPI_SIG_CSRT "CSRT" /* Core System Resource Table */ | ||
| 67 | #define ACPI_SIG_DBG2 "DBG2" /* Debug Port table type 2 */ | ||
| 66 | #define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ | 68 | #define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ |
| 67 | #define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ | 69 | #define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ |
| 68 | #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ | 70 | #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ |
| @@ -96,9 +98,15 @@ | |||
| 96 | #pragma pack(1) | 98 | #pragma pack(1) |
| 97 | 99 | ||
| 98 | /* | 100 | /* |
| 99 | * Note about bitfields: The u8 type is used for bitfields in ACPI tables. | 101 | * Note: C bitfields are not used for this reason: |
| 100 | * This is the only type that is even remotely portable. Anything else is not | 102 | * |
| 101 | * portable, so do not use any other bitfield types. | 103 | * "Bitfields are great and easy to read, but unfortunately the C language |
| 104 | * does not specify the layout of bitfields in memory, which means they are | ||
| 105 | * essentially useless for dealing with packed data in on-disk formats or | ||
| 106 | * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, | ||
| 107 | * this decision was a design error in C. Ritchie could have picked an order | ||
| 108 | * and stuck with it." Norman Ramsey. | ||
| 109 | * See http://stackoverflow.com/a/1053662/41661 | ||
| 102 | */ | 110 | */ |
| 103 | 111 | ||
| 104 | /******************************************************************************* | 112 | /******************************************************************************* |
| @@ -232,6 +240,115 @@ struct acpi_table_boot { | |||
| 232 | 240 | ||
| 233 | /******************************************************************************* | 241 | /******************************************************************************* |
| 234 | * | 242 | * |
| 243 | * CSRT - Core System Resource Table | ||
| 244 | * Version 0 | ||
| 245 | * | ||
| 246 | * Conforms to the "Core System Resource Table (CSRT)", November 14, 2011 | ||
| 247 | * | ||
| 248 | ******************************************************************************/ | ||
| 249 | |||
| 250 | struct acpi_table_csrt { | ||
| 251 | struct acpi_table_header header; /* Common ACPI table header */ | ||
| 252 | }; | ||
| 253 | |||
| 254 | /* Resource Group subtable */ | ||
| 255 | |||
| 256 | struct acpi_csrt_group { | ||
| 257 | u32 length; | ||
| 258 | u32 vendor_id; | ||
| 259 | u32 subvendor_id; | ||
| 260 | u16 device_id; | ||
| 261 | u16 subdevice_id; | ||
| 262 | u16 revision; | ||
| 263 | u16 reserved; | ||
| 264 | u32 info_length; | ||
| 265 | |||
| 266 | /* Shared data (length = info_length) immediately follows */ | ||
| 267 | }; | ||
| 268 | |||
| 269 | /* Resource Descriptor subtable */ | ||
| 270 | |||
| 271 | struct acpi_csrt_descriptor { | ||
| 272 | u32 length; | ||
| 273 | u16 type; | ||
| 274 | u16 subtype; | ||
| 275 | u32 uid; | ||
| 276 | |||
| 277 | /* Resource-specific information immediately follows */ | ||
| 278 | }; | ||
| 279 | |||
| 280 | /* Resource Types */ | ||
| 281 | |||
| 282 | #define ACPI_CSRT_TYPE_INTERRUPT 0x0001 | ||
| 283 | #define ACPI_CSRT_TYPE_TIMER 0x0002 | ||
| 284 | #define ACPI_CSRT_TYPE_DMA 0x0003 | ||
| 285 | |||
| 286 | /* Resource Subtypes */ | ||
| 287 | |||
| 288 | #define ACPI_CSRT_XRUPT_LINE 0x0000 | ||
| 289 | #define ACPI_CSRT_XRUPT_CONTROLLER 0x0001 | ||
| 290 | #define ACPI_CSRT_TIMER 0x0000 | ||
| 291 | #define ACPI_CSRT_DMA_CHANNEL 0x0000 | ||
| 292 | #define ACPI_CSRT_DMA_CONTROLLER 0x0001 | ||
| 293 | |||
| 294 | /******************************************************************************* | ||
| 295 | * | ||
| 296 | * DBG2 - Debug Port Table 2 | ||
| 297 | * Version 0 (Both main table and subtables) | ||
| 298 | * | ||
| 299 | * Conforms to "Microsoft Debug Port Table 2 (DBG2)", May 22 2012. | ||
| 300 | * | ||
| 301 | ******************************************************************************/ | ||
| 302 | |||
| 303 | struct acpi_table_dbg2 { | ||
| 304 | struct acpi_table_header header; /* Common ACPI table header */ | ||
| 305 | u32 info_offset; | ||
| 306 | u32 info_count; | ||
| 307 | }; | ||
| 308 | |||
| 309 | /* Debug Device Information Subtable */ | ||
| 310 | |||
| 311 | struct acpi_dbg2_device { | ||
| 312 | u8 revision; | ||
| 313 | u16 length; | ||
| 314 | u8 register_count; /* Number of base_address registers */ | ||
| 315 | u16 namepath_length; | ||
| 316 | u16 namepath_offset; | ||
| 317 | u16 oem_data_length; | ||
| 318 | u16 oem_data_offset; | ||
| 319 | u16 port_type; | ||
| 320 | u16 port_subtype; | ||
| 321 | u16 reserved; | ||
| 322 | u16 base_address_offset; | ||
| 323 | u16 address_size_offset; | ||
| 324 | /* | ||
| 325 | * Data that follows: | ||
| 326 | * base_address (required) - Each in 12-byte Generic Address Structure format. | ||
| 327 | * address_size (required) - Array of u32 sizes corresponding to each base_address register. | ||
| 328 | * Namepath (required) - Null terminated string. Single dot if not supported. | ||
| 329 | * oem_data (optional) - Length is oem_data_length. | ||
| 330 | */ | ||
| 331 | }; | ||
| 332 | |||
| 333 | /* Types for port_type field above */ | ||
| 334 | |||
| 335 | #define ACPI_DBG2_SERIAL_PORT 0x8000 | ||
| 336 | #define ACPI_DBG2_1394_PORT 0x8001 | ||
| 337 | #define ACPI_DBG2_USB_PORT 0x8002 | ||
| 338 | #define ACPI_DBG2_NET_PORT 0x8003 | ||
| 339 | |||
| 340 | /* Subtypes for port_subtype field above */ | ||
| 341 | |||
| 342 | #define ACPI_DBG2_16550_COMPATIBLE 0x0000 | ||
| 343 | #define ACPI_DBG2_16550_SUBSET 0x0001 | ||
| 344 | |||
| 345 | #define ACPI_DBG2_1394_STANDARD 0x0000 | ||
| 346 | |||
| 347 | #define ACPI_DBG2_USB_XHCI 0x0000 | ||
| 348 | #define ACPI_DBG2_USB_EHCI 0x0001 | ||
| 349 | |||
| 350 | /******************************************************************************* | ||
| 351 | * | ||
| 235 | * DBGP - Debug Port table | 352 | * DBGP - Debug Port table |
| 236 | * Version 1 | 353 | * Version 1 |
| 237 | * | 354 | * |
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index f65a0ed869eb..8c61b5fe42a4 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h | |||
| @@ -75,7 +75,6 @@ | |||
| 75 | /* Reserved table signatures */ | 75 | /* Reserved table signatures */ |
| 76 | 76 | ||
| 77 | #define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */ | 77 | #define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */ |
| 78 | #define ACPI_SIG_DBG2 "DBG2" /* Debug Port table 2 */ | ||
| 79 | #define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */ | 78 | #define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */ |
| 80 | #define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ | 79 | #define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ |
| 81 | #define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */ | 80 | #define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */ |
| @@ -87,9 +86,15 @@ | |||
| 87 | #pragma pack(1) | 86 | #pragma pack(1) |
| 88 | 87 | ||
| 89 | /* | 88 | /* |
| 90 | * Note about bitfields: The u8 type is used for bitfields in ACPI tables. | 89 | * Note: C bitfields are not used for this reason: |
| 91 | * This is the only type that is even remotely portable. Anything else is not | 90 | * |
| 92 | * portable, so do not use any other bitfield types. | 91 | * "Bitfields are great and easy to read, but unfortunately the C language |
| 92 | * does not specify the layout of bitfields in memory, which means they are | ||
| 93 | * essentially useless for dealing with packed data in on-disk formats or | ||
| 94 | * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, | ||
| 95 | * this decision was a design error in C. Ritchie could have picked an order | ||
| 96 | * and stuck with it." Norman Ramsey. | ||
| 97 | * See http://stackoverflow.com/a/1053662/41661 | ||
| 93 | */ | 98 | */ |
| 94 | 99 | ||
| 95 | /******************************************************************************* | 100 | /******************************************************************************* |
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 3d00bd5bd7e3..a85bae968262 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h | |||
| @@ -519,13 +519,6 @@ typedef u64 acpi_integer; | |||
| 519 | #define ACPI_SLEEP_TYPE_INVALID 0xFF | 519 | #define ACPI_SLEEP_TYPE_INVALID 0xFF |
| 520 | 520 | ||
| 521 | /* | 521 | /* |
| 522 | * Sleep/Wake flags | ||
| 523 | */ | ||
| 524 | #define ACPI_NO_OPTIONAL_METHODS 0x00 /* Do not execute any optional methods */ | ||
| 525 | #define ACPI_EXECUTE_GTS 0x01 /* For enter sleep interface */ | ||
| 526 | #define ACPI_EXECUTE_BFS 0x02 /* For leave sleep prep interface */ | ||
| 527 | |||
| 528 | /* | ||
| 529 | * Standard notify values | 522 | * Standard notify values |
| 530 | */ | 523 | */ |
| 531 | #define ACPI_NOTIFY_BUS_CHECK (u8) 0x00 | 524 | #define ACPI_NOTIFY_BUS_CHECK (u8) 0x00 |
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile new file mode 100644 index 000000000000..6b9cf7a987c7 --- /dev/null +++ b/tools/power/acpi/Makefile | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | PROG= acpidump | ||
| 2 | SRCS= acpidump.c | ||
| 3 | KERNEL_INCLUDE := ../../../include | ||
| 4 | CFLAGS += -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) | ||
| 5 | |||
| 6 | all: acpidump | ||
| 7 | $(PROG) : $(SRCS) | ||
| 8 | $(CC) $(CFLAGS) $(SRCS) -o $(PROG) | ||
| 9 | |||
| 10 | CLEANFILES= $(PROG) | ||
| 11 | |||
| 12 | clean : | ||
| 13 | rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~ | ||
| 14 | |||
| 15 | install : | ||
| 16 | install acpidump /usr/bin/acpidump | ||
| 17 | install acpidump.8 /usr/share/man/man8 | ||
| 18 | |||
diff --git a/tools/power/acpi/acpidump.8 b/tools/power/acpi/acpidump.8 new file mode 100644 index 000000000000..adfa99166e5e --- /dev/null +++ b/tools/power/acpi/acpidump.8 | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | .TH ACPIDUMP 8 | ||
| 2 | .SH NAME | ||
| 3 | acpidump \- Dump system's ACPI tables to an ASCII file. | ||
| 4 | .SH SYNOPSIS | ||
| 5 | .ft B | ||
| 6 | .B acpidump > acpidump.out | ||
| 7 | .SH DESCRIPTION | ||
| 8 | \fBacpidump \fP dumps the systems ACPI tables to an ASCII file | ||
| 9 | appropriate for attaching to a bug report. | ||
| 10 | |||
| 11 | Subsequently, they can be processed by utilities in the ACPICA package. | ||
| 12 | .SS Options | ||
| 13 | no options worth worrying about. | ||
| 14 | .PP | ||
| 15 | .SH EXAMPLE | ||
| 16 | |||
| 17 | .nf | ||
| 18 | # acpidump > acpidump.out | ||
| 19 | |||
| 20 | $ acpixtract -a acpidump.out | ||
| 21 | Acpi table [DSDT] - 15974 bytes written to DSDT.dat | ||
| 22 | Acpi table [FACS] - 64 bytes written to FACS.dat | ||
| 23 | Acpi table [FACP] - 116 bytes written to FACP.dat | ||
| 24 | Acpi table [APIC] - 120 bytes written to APIC.dat | ||
| 25 | Acpi table [MCFG] - 60 bytes written to MCFG.dat | ||
| 26 | Acpi table [SSDT] - 444 bytes written to SSDT1.dat | ||
| 27 | Acpi table [SSDT] - 439 bytes written to SSDT2.dat | ||
| 28 | Acpi table [SSDT] - 439 bytes written to SSDT3.dat | ||
| 29 | Acpi table [SSDT] - 439 bytes written to SSDT4.dat | ||
| 30 | Acpi table [SSDT] - 439 bytes written to SSDT5.dat | ||
| 31 | Acpi table [RSDT] - 76 bytes written to RSDT.dat | ||
| 32 | Acpi table [RSDP] - 20 bytes written to RSDP.dat | ||
| 33 | |||
| 34 | $ iasl -d *.dat | ||
| 35 | ... | ||
| 36 | .fi | ||
| 37 | creates *.dsl, a human readable form which can be edited | ||
| 38 | and compiled using iasl. | ||
| 39 | |||
| 40 | |||
| 41 | .SH NOTES | ||
| 42 | |||
| 43 | .B "acpidump " | ||
| 44 | must be run as root. | ||
| 45 | |||
| 46 | .SH REFERENCES | ||
| 47 | ACPICA: https://acpica.org/ | ||
| 48 | |||
| 49 | .SH FILES | ||
| 50 | .ta | ||
| 51 | .nf | ||
| 52 | /dev/mem | ||
| 53 | /sys/firmware/acpi/tables/dynamic/* | ||
| 54 | .fi | ||
| 55 | |||
| 56 | .PP | ||
| 57 | .SH AUTHOR | ||
| 58 | .nf | ||
| 59 | Written by Len Brown <len.brown@intel.com> | ||
diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c new file mode 100644 index 000000000000..07779871421c --- /dev/null +++ b/tools/power/acpi/acpidump.c | |||
| @@ -0,0 +1,560 @@ | |||
| 1 | /* | ||
| 2 | * (c) Alexey Starikovskiy, Intel, 2005-2006. | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions | ||
| 7 | * are met: | ||
| 8 | * 1. Redistributions of source code must retain the above copyright | ||
| 9 | * notice, this list of conditions, and the following disclaimer, | ||
| 10 | * without modification. | ||
| 11 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
| 12 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
| 13 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
| 14 | * including a substantially similar Disclaimer requirement for further | ||
| 15 | * binary redistribution. | ||
| 16 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
| 17 | * of any contributors may be used to endorse or promote products derived | ||
| 18 | * from this software without specific prior written permission. | ||
| 19 | * | ||
| 20 | * Alternatively, this software may be distributed under the terms of the | ||
| 21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
| 22 | * Software Foundation. | ||
| 23 | * | ||
| 24 | * NO WARRANTY | ||
| 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
| 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 29 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 33 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
| 34 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 35 | * POSSIBILITY OF SUCH DAMAGES. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #ifdef DEFINE_ALTERNATE_TYPES | ||
| 39 | /* hack to enable building old application with new headers -lenb */ | ||
| 40 | #define acpi_fadt_descriptor acpi_table_fadt | ||
| 41 | #define acpi_rsdp_descriptor acpi_table_rsdp | ||
| 42 | #define DSDT_SIG ACPI_SIG_DSDT | ||
| 43 | #define FACS_SIG ACPI_SIG_FACS | ||
| 44 | #define FADT_SIG ACPI_SIG_FADT | ||
| 45 | #define xfirmware_ctrl Xfacs | ||
| 46 | #define firmware_ctrl facs | ||
| 47 | |||
| 48 | typedef int s32; | ||
| 49 | typedef unsigned char u8; | ||
| 50 | typedef unsigned short u16; | ||
| 51 | typedef unsigned int u32; | ||
| 52 | typedef unsigned long long u64; | ||
| 53 | typedef long long s64; | ||
| 54 | #endif | ||
| 55 | |||
| 56 | #include <sys/mman.h> | ||
| 57 | #include <sys/types.h> | ||
| 58 | #include <sys/stat.h> | ||
| 59 | #include <fcntl.h> | ||
| 60 | #include <stdio.h> | ||
| 61 | #include <string.h> | ||
| 62 | #include <unistd.h> | ||
| 63 | #include <getopt.h> | ||
| 64 | |||
| 65 | #include <sys/types.h> | ||
| 66 | #include <dirent.h> | ||
| 67 | |||
| 68 | #include <acpi/acconfig.h> | ||
| 69 | #include <acpi/platform/acenv.h> | ||
| 70 | #include <acpi/actypes.h> | ||
| 71 | #include <acpi/actbl.h> | ||
| 72 | |||
| 73 | static inline u8 checksum(u8 * buffer, u32 length) | ||
| 74 | { | ||
| 75 | u8 sum = 0, *i = buffer; | ||
| 76 | buffer += length; | ||
| 77 | for (; i < buffer; sum += *(i++)); | ||
| 78 | return sum; | ||
| 79 | } | ||
| 80 | |||
| 81 | static unsigned long psz, addr, length; | ||
| 82 | static int print, connect, skip; | ||
| 83 | static u8 select_sig[4]; | ||
| 84 | |||
| 85 | static unsigned long read_efi_systab( void ) | ||
| 86 | { | ||
| 87 | char buffer[80]; | ||
| 88 | unsigned long addr; | ||
| 89 | FILE *f = fopen("/sys/firmware/efi/systab", "r"); | ||
| 90 | if (f) { | ||
| 91 | while (fgets(buffer, 80, f)) { | ||
| 92 | if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1) | ||
| 93 | return addr; | ||
| 94 | } | ||
| 95 | fclose(f); | ||
| 96 | } | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static u8 *acpi_map_memory(unsigned long where, unsigned length) | ||
| 101 | { | ||
| 102 | unsigned long offset; | ||
| 103 | u8 *there; | ||
| 104 | int fd = open("/dev/mem", O_RDONLY); | ||
| 105 | if (fd < 0) { | ||
| 106 | fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n"); | ||
| 107 | exit(1); | ||
| 108 | } | ||
| 109 | offset = where % psz; | ||
| 110 | there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE, | ||
| 111 | fd, where - offset); | ||
| 112 | close(fd); | ||
| 113 | if (there == MAP_FAILED) return 0; | ||
| 114 | return (there + offset); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void acpi_unmap_memory(u8 * there, unsigned length) | ||
| 118 | { | ||
| 119 | unsigned long offset = (unsigned long)there % psz; | ||
| 120 | munmap(there - offset, length + offset); | ||
| 121 | } | ||
| 122 | |||
| 123 | static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig) | ||
| 124 | { | ||
| 125 | unsigned size; | ||
| 126 | struct acpi_table_header *tbl = (struct acpi_table_header *) | ||
| 127 | acpi_map_memory(where, sizeof(struct acpi_table_header)); | ||
| 128 | if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0; | ||
| 129 | size = tbl->length; | ||
| 130 | acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header)); | ||
| 131 | return (struct acpi_table_header *)acpi_map_memory(where, size); | ||
| 132 | } | ||
| 133 | |||
| 134 | static void acpi_unmap_table(struct acpi_table_header *tbl) | ||
| 135 | { | ||
| 136 | acpi_unmap_memory((u8 *)tbl, tbl->length); | ||
| 137 | } | ||
| 138 | |||
| 139 | static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length) | ||
| 140 | { | ||
| 141 | struct acpi_rsdp_descriptor *rsdp; | ||
| 142 | u8 *i, *end = begin + length; | ||
| 143 | /* Search from given start address for the requested length */ | ||
| 144 | for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) { | ||
| 145 | /* The signature and checksum must both be correct */ | ||
| 146 | if (memcmp((char *)i, "RSD PTR ", 8)) continue; | ||
| 147 | rsdp = (struct acpi_rsdp_descriptor *)i; | ||
| 148 | /* Signature matches, check the appropriate checksum */ | ||
| 149 | if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ? | ||
| 150 | ACPI_RSDP_CHECKSUM_LENGTH : | ||
| 151 | ACPI_RSDP_XCHECKSUM_LENGTH)) | ||
| 152 | /* Checksum valid, we have found a valid RSDP */ | ||
| 153 | return rsdp; | ||
| 154 | } | ||
| 155 | /* Searched entire block, no RSDP was found */ | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Output data | ||
| 161 | */ | ||
| 162 | static void acpi_show_data(int fd, u8 * data, int size) | ||
| 163 | { | ||
| 164 | char buffer[256]; | ||
| 165 | int len; | ||
| 166 | int i, remain = size; | ||
| 167 | while (remain > 0) { | ||
| 168 | len = snprintf(buffer, 256, " %04x:", size - remain); | ||
| 169 | for (i = 0; i < 16 && i < remain; i++) { | ||
| 170 | len += | ||
| 171 | snprintf(&buffer[len], 256 - len, " %02x", data[i]); | ||
| 172 | } | ||
| 173 | for (; i < 16; i++) { | ||
| 174 | len += snprintf(&buffer[len], 256 - len, " "); | ||
| 175 | } | ||
| 176 | len += snprintf(&buffer[len], 256 - len, " "); | ||
| 177 | for (i = 0; i < 16 && i < remain; i++) { | ||
| 178 | buffer[len++] = (isprint(data[i])) ? data[i] : '.'; | ||
| 179 | } | ||
| 180 | buffer[len++] = '\n'; | ||
| 181 | write(fd, buffer, len); | ||
| 182 | data += 16; | ||
| 183 | remain -= 16; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | ||
| 188 | * Output ACPI table | ||
| 189 | */ | ||
| 190 | static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) | ||
| 191 | { | ||
| 192 | char buff[80]; | ||
| 193 | int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr); | ||
| 194 | write(fd, buff, len); | ||
| 195 | acpi_show_data(fd, (u8 *) table, table->length); | ||
| 196 | buff[0] = '\n'; | ||
| 197 | write(fd, buff, 1); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) | ||
| 201 | { | ||
| 202 | static int select_done = 0; | ||
| 203 | if (!select_sig[0]) { | ||
| 204 | if (print) { | ||
| 205 | acpi_show_table(fd, tbl, addr); | ||
| 206 | } else { | ||
| 207 | write(fd, tbl, tbl->length); | ||
| 208 | } | ||
| 209 | } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) { | ||
| 210 | if (skip > 0) { | ||
| 211 | --skip; | ||
| 212 | return; | ||
| 213 | } | ||
| 214 | if (print) { | ||
| 215 | acpi_show_table(fd, tbl, addr); | ||
| 216 | } else { | ||
| 217 | write(fd, tbl, tbl->length); | ||
| 218 | } | ||
| 219 | select_done = 1; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { | ||
| 224 | struct acpi_fadt_descriptor x; | ||
| 225 | unsigned long addr; | ||
| 226 | size_t len = sizeof(struct acpi_fadt_descriptor); | ||
| 227 | if (len > tbl->length) len = tbl->length; | ||
| 228 | memcpy(&x, tbl, len); | ||
| 229 | x.header.length = len; | ||
| 230 | if (checksum((u8 *)tbl, len)) { | ||
| 231 | fprintf(stderr, "Wrong checksum for FADT!\n"); | ||
| 232 | } | ||
| 233 | if (x.header.length >= 148 && x.Xdsdt) { | ||
| 234 | addr = (unsigned long)x.Xdsdt; | ||
| 235 | if (connect) { | ||
| 236 | x.Xdsdt = lseek(fd, 0, SEEK_CUR); | ||
| 237 | } | ||
| 238 | } else if (x.header.length >= 44 && x.dsdt) { | ||
| 239 | addr = (unsigned long)x.dsdt; | ||
| 240 | if (connect) { | ||
| 241 | x.dsdt = lseek(fd, 0, SEEK_CUR); | ||
| 242 | } | ||
| 243 | } else { | ||
| 244 | fprintf(stderr, "No DSDT in FADT!\n"); | ||
| 245 | goto no_dsdt; | ||
| 246 | } | ||
| 247 | tbl = acpi_map_table(addr, DSDT_SIG); | ||
| 248 | if (!tbl) goto no_dsdt; | ||
| 249 | if (checksum((u8 *)tbl, tbl->length)) | ||
| 250 | fprintf(stderr, "Wrong checksum for DSDT!\n"); | ||
| 251 | write_table(fd, tbl, addr); | ||
| 252 | acpi_unmap_table(tbl); | ||
| 253 | no_dsdt: | ||
| 254 | if (x.header.length >= 140 && x.xfirmware_ctrl) { | ||
| 255 | addr = (unsigned long)x.xfirmware_ctrl; | ||
| 256 | if (connect) { | ||
| 257 | x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR); | ||
| 258 | } | ||
| 259 | } else if (x.header.length >= 40 && x.firmware_ctrl) { | ||
| 260 | addr = (unsigned long)x.firmware_ctrl; | ||
| 261 | if (connect) { | ||
| 262 | x.firmware_ctrl = lseek(fd, 0, SEEK_CUR); | ||
| 263 | } | ||
| 264 | } else { | ||
| 265 | fprintf(stderr, "No FACS in FADT!\n"); | ||
| 266 | goto no_facs; | ||
| 267 | } | ||
| 268 | tbl = acpi_map_table(addr, FACS_SIG); | ||
| 269 | if (!tbl) goto no_facs; | ||
| 270 | /* do not checksum FACS */ | ||
| 271 | write_table(fd, tbl, addr); | ||
| 272 | acpi_unmap_table(tbl); | ||
| 273 | no_facs: | ||
| 274 | write_table(fd, (struct acpi_table_header *)&x, xaddr); | ||
| 275 | } | ||
| 276 | |||
| 277 | static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) | ||
| 278 | { | ||
| 279 | struct acpi_table_header *sdt, *tbl = 0; | ||
| 280 | int xsdt = 1, i, num; | ||
| 281 | char *offset; | ||
| 282 | unsigned long addr; | ||
| 283 | if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { | ||
| 284 | tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); | ||
| 285 | } | ||
| 286 | if (!tbl && rsdp->rsdt_physical_address) { | ||
| 287 | xsdt = 0; | ||
| 288 | tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); | ||
| 289 | } | ||
| 290 | if (!tbl) return 0; | ||
| 291 | sdt = malloc(tbl->length); | ||
| 292 | memcpy(sdt, tbl, tbl->length); | ||
| 293 | acpi_unmap_table(tbl); | ||
| 294 | if (checksum((u8 *)sdt, sdt->length)) | ||
| 295 | fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); | ||
| 296 | num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); | ||
| 297 | offset = (char *)sdt + sizeof(struct acpi_table_header); | ||
| 298 | for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { | ||
| 299 | addr = (xsdt) ? (unsigned long)(*(u64 *)offset): | ||
| 300 | (unsigned long)(*(u32 *)offset); | ||
| 301 | if (!addr) continue; | ||
| 302 | tbl = acpi_map_table(addr, 0); | ||
| 303 | if (!tbl) continue; | ||
| 304 | if (!memcmp(tbl->signature, FADT_SIG, 4)) { | ||
| 305 | acpi_dump_FADT(fd, tbl, addr); | ||
| 306 | } else { | ||
| 307 | if (checksum((u8 *)tbl, tbl->length)) | ||
| 308 | fprintf(stderr, "Wrong checksum for generic table!\n"); | ||
| 309 | write_table(fd, tbl, addr); | ||
| 310 | } | ||
| 311 | acpi_unmap_table(tbl); | ||
| 312 | if (connect) { | ||
| 313 | if (xsdt) | ||
| 314 | (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); | ||
| 315 | else | ||
| 316 | (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | if (xsdt) { | ||
| 320 | addr = (unsigned long)rsdp->xsdt_physical_address; | ||
| 321 | if (connect) { | ||
| 322 | rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); | ||
| 323 | } | ||
| 324 | } else { | ||
| 325 | addr = (unsigned long)rsdp->rsdt_physical_address; | ||
| 326 | if (connect) { | ||
| 327 | rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | write_table(fd, sdt, addr); | ||
| 331 | free (sdt); | ||
| 332 | return 1; | ||
| 333 | } | ||
| 334 | |||
| 335 | #define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic" | ||
| 336 | |||
| 337 | static void acpi_dump_dynamic_SSDT(int fd) | ||
| 338 | { | ||
| 339 | struct stat file_stat; | ||
| 340 | char filename[256], *ptr; | ||
| 341 | DIR *tabledir; | ||
| 342 | struct dirent *entry; | ||
| 343 | FILE *fp; | ||
| 344 | int count, readcount, length; | ||
| 345 | struct acpi_table_header table_header, *ptable; | ||
| 346 | |||
| 347 | if (stat(DYNAMIC_SSDT, &file_stat) == -1) { | ||
| 348 | /* The directory doesn't exist */ | ||
| 349 | return; | ||
| 350 | } | ||
| 351 | tabledir = opendir(DYNAMIC_SSDT); | ||
| 352 | if(!tabledir){ | ||
| 353 | /*can't open the directory */ | ||
| 354 | return; | ||
| 355 | } | ||
| 356 | |||
| 357 | while ((entry = readdir(tabledir)) != 0){ | ||
| 358 | /* skip the file of . /.. */ | ||
| 359 | if (entry->d_name[0] == '.') | ||
| 360 | continue; | ||
| 361 | |||
| 362 | sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name); | ||
| 363 | fp = fopen(filename, "r"); | ||
| 364 | if (fp == NULL) { | ||
| 365 | fprintf(stderr, "Can't open the file of %s\n", | ||
| 366 | filename); | ||
| 367 | continue; | ||
| 368 | } | ||
| 369 | /* Read the Table header to parse the table length */ | ||
| 370 | count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); | ||
| 371 | if (count < sizeof(table_header)) { | ||
| 372 | /* the length is lessn than ACPI table header. skip it */ | ||
| 373 | fclose(fp); | ||
| 374 | continue; | ||
| 375 | } | ||
| 376 | length = table_header.length; | ||
| 377 | ptr = malloc(table_header.length); | ||
| 378 | fseek(fp, 0, SEEK_SET); | ||
| 379 | readcount = 0; | ||
| 380 | while(!feof(fp) && readcount < length) { | ||
| 381 | count = fread(ptr + readcount, 1, 256, fp); | ||
| 382 | readcount += count; | ||
| 383 | } | ||
| 384 | fclose(fp); | ||
| 385 | ptable = (struct acpi_table_header *) ptr; | ||
| 386 | if (checksum((u8 *) ptable, ptable->length)) | ||
| 387 | fprintf(stderr, "Wrong checksum " | ||
| 388 | "for dynamic SSDT table!\n"); | ||
| 389 | write_table(fd, ptable, 0); | ||
| 390 | free(ptr); | ||
| 391 | } | ||
| 392 | closedir(tabledir); | ||
| 393 | return; | ||
| 394 | } | ||
| 395 | |||
| 396 | static void usage(const char *progname) | ||
| 397 | { | ||
| 398 | puts("Usage:"); | ||
| 399 | printf("%s [--addr 0x1234][--table DSDT][--output filename]" | ||
| 400 | "[--binary][--length 0x456][--help]\n", progname); | ||
| 401 | puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address"); | ||
| 402 | puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature"); | ||
| 403 | puts("\t--output filename or -o filename -- redirect output from stdin to filename"); | ||
| 404 | puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format"); | ||
| 405 | puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory" | ||
| 406 | "\n\t\tregion without trying to understand it's contents"); | ||
| 407 | puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one"); | ||
| 408 | puts("\t--help or -h -- this help message"); | ||
| 409 | exit(0); | ||
| 410 | } | ||
| 411 | |||
| 412 | static struct option long_options[] = { | ||
| 413 | {"addr", 1, 0, 0}, | ||
| 414 | {"table", 1, 0, 0}, | ||
| 415 | {"output", 1, 0, 0}, | ||
| 416 | {"binary", 0, 0, 0}, | ||
| 417 | {"length", 1, 0, 0}, | ||
| 418 | {"skip", 1, 0, 0}, | ||
| 419 | {"help", 0, 0, 0}, | ||
| 420 | {0, 0, 0, 0} | ||
| 421 | }; | ||
| 422 | int main(int argc, char **argv) | ||
| 423 | { | ||
| 424 | int option_index, c, fd; | ||
| 425 | u8 *raw; | ||
| 426 | struct acpi_rsdp_descriptor rsdpx, *x = 0; | ||
| 427 | char *filename = 0; | ||
| 428 | char buff[80]; | ||
| 429 | memset(select_sig, 0, 4); | ||
| 430 | print = 1; | ||
| 431 | connect = 0; | ||
| 432 | addr = length = 0; | ||
| 433 | skip = 0; | ||
| 434 | while (1) { | ||
| 435 | option_index = 0; | ||
| 436 | c = getopt_long(argc, argv, "a:t:o:bl:s:h", | ||
| 437 | long_options, &option_index); | ||
| 438 | if (c == -1) | ||
| 439 | break; | ||
| 440 | |||
| 441 | switch (c) { | ||
| 442 | case 0: | ||
| 443 | switch (option_index) { | ||
| 444 | case 0: | ||
| 445 | addr = strtoul(optarg, (char **)NULL, 16); | ||
| 446 | break; | ||
| 447 | case 1: | ||
| 448 | memcpy(select_sig, optarg, 4); | ||
| 449 | break; | ||
| 450 | case 2: | ||
| 451 | filename = optarg; | ||
| 452 | break; | ||
| 453 | case 3: | ||
| 454 | print = 0; | ||
| 455 | break; | ||
| 456 | case 4: | ||
| 457 | length = strtoul(optarg, (char **)NULL, 16); | ||
| 458 | break; | ||
| 459 | case 5: | ||
| 460 | skip = strtoul(optarg, (char **)NULL, 10); | ||
| 461 | break; | ||
| 462 | case 6: | ||
| 463 | usage(argv[0]); | ||
| 464 | exit(0); | ||
| 465 | } | ||
| 466 | break; | ||
| 467 | case 'a': | ||
| 468 | addr = strtoul(optarg, (char **)NULL, 16); | ||
| 469 | break; | ||
| 470 | case 't': | ||
| 471 | memcpy(select_sig, optarg, 4); | ||
| 472 | break; | ||
| 473 | case 'o': | ||
| 474 | filename = optarg; | ||
| 475 | break; | ||
| 476 | case 'b': | ||
| 477 | print = 0; | ||
| 478 | break; | ||
| 479 | case 'l': | ||
| 480 | length = strtoul(optarg, (char **)NULL, 16); | ||
| 481 | break; | ||
| 482 | case 's': | ||
| 483 | skip = strtoul(optarg, (char **)NULL, 10); | ||
| 484 | break; | ||
| 485 | case 'h': | ||
| 486 | usage(argv[0]); | ||
| 487 | exit(0); | ||
| 488 | default: | ||
| 489 | printf("Unknown option!\n"); | ||
| 490 | usage(argv[0]); | ||
| 491 | exit(0); | ||
| 492 | } | ||
| 493 | } | ||
| 494 | |||
| 495 | fd = STDOUT_FILENO; | ||
| 496 | if (filename) { | ||
| 497 | fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | ||
| 498 | if (fd < 0) | ||
| 499 | return fd; | ||
| 500 | } | ||
| 501 | |||
| 502 | if (!select_sig[0] && !print) { | ||
| 503 | connect = 1; | ||
| 504 | } | ||
| 505 | |||
| 506 | psz = sysconf(_SC_PAGESIZE); | ||
| 507 | if (length && addr) { | ||
| 508 | /* We know length and address, it means we just want a memory dump */ | ||
| 509 | if (!(raw = acpi_map_memory(addr, length))) | ||
| 510 | goto not_found; | ||
| 511 | write(fd, raw, length); | ||
| 512 | acpi_unmap_memory(raw, length); | ||
| 513 | close(fd); | ||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | length = sizeof(struct acpi_rsdp_descriptor); | ||
| 518 | if (!addr) { | ||
| 519 | addr = read_efi_systab(); | ||
| 520 | if (!addr) { | ||
| 521 | addr = ACPI_HI_RSDP_WINDOW_BASE; | ||
| 522 | length = ACPI_HI_RSDP_WINDOW_SIZE; | ||
| 523 | } | ||
| 524 | } | ||
| 525 | |||
| 526 | if (!(raw = acpi_map_memory(addr, length)) || | ||
| 527 | !(x = acpi_scan_for_rsdp(raw, length))) | ||
| 528 | goto not_found; | ||
| 529 | |||
| 530 | /* Find RSDP and print all found tables */ | ||
| 531 | memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor)); | ||
| 532 | acpi_unmap_memory(raw, length); | ||
| 533 | if (connect) { | ||
| 534 | lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); | ||
| 535 | } | ||
| 536 | if (!acpi_dump_SDT(fd, &rsdpx)) | ||
| 537 | goto not_found; | ||
| 538 | if (connect) { | ||
| 539 | lseek(fd, 0, SEEK_SET); | ||
| 540 | write(fd, x, (rsdpx.revision < 2) ? | ||
| 541 | ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); | ||
| 542 | } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) { | ||
| 543 | addr += (long)x - (long)raw; | ||
| 544 | length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr); | ||
| 545 | write(fd, buff, length); | ||
| 546 | acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ? | ||
| 547 | ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); | ||
| 548 | buff[0] = '\n'; | ||
| 549 | write(fd, buff, 1); | ||
| 550 | } | ||
| 551 | acpi_dump_dynamic_SSDT(fd); | ||
| 552 | close(fd); | ||
| 553 | return 0; | ||
| 554 | not_found: | ||
| 555 | close(fd); | ||
| 556 | fprintf(stderr, "ACPI tables were not found. If you know location " | ||
| 557 | "of RSD PTR table (from dmesg, etc), " | ||
| 558 | "supply it with either --addr or -a option\n"); | ||
| 559 | return 1; | ||
| 560 | } | ||
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 74e44507dfe9..e4d0690cccf9 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 | |||
| @@ -4,15 +4,11 @@ turbostat \- Report processor frequency and idle statistics | |||
| 4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
| 5 | .ft B | 5 | .ft B |
| 6 | .B turbostat | 6 | .B turbostat |
| 7 | .RB [ "\-s" ] | 7 | .RB [ Options ] |
| 8 | .RB [ "\-v" ] | ||
| 9 | .RB [ "\-M MSR#" ] | ||
| 10 | .RB command | 8 | .RB command |
| 11 | .br | 9 | .br |
| 12 | .B turbostat | 10 | .B turbostat |
| 13 | .RB [ "\-s" ] | 11 | .RB [ Options ] |
| 14 | .RB [ "\-v" ] | ||
| 15 | .RB [ "\-M MSR#" ] | ||
| 16 | .RB [ "\-i interval_sec" ] | 12 | .RB [ "\-i interval_sec" ] |
| 17 | .SH DESCRIPTION | 13 | .SH DESCRIPTION |
| 18 | \fBturbostat \fP reports processor topology, frequency | 14 | \fBturbostat \fP reports processor topology, frequency |
| @@ -27,16 +23,23 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs. | |||
| 27 | on processors that additionally support C-state residency counters. | 23 | on processors that additionally support C-state residency counters. |
| 28 | 24 | ||
| 29 | .SS Options | 25 | .SS Options |
| 30 | The \fB-s\fP option limits output to a 1-line system summary for each interval. | 26 | The \fB-p\fP option limits output to the 1st thread in 1st core of each package. |
| 31 | .PP | 27 | .PP |
| 32 | The \fB-c\fP option limits output to the 1st thread in each core. | 28 | The \fB-P\fP option limits output to the 1st thread in each Package. |
| 33 | .PP | 29 | .PP |
| 34 | The \fB-p\fP option limits output to the 1st thread in each package. | 30 | The \fB-S\fP option limits output to a 1-line System Summary for each interval. |
| 35 | .PP | 31 | .PP |
| 36 | The \fB-v\fP option increases verbosity. | 32 | The \fB-v\fP option increases verbosity. |
| 37 | .PP | 33 | .PP |
| 38 | The \fB-M MSR#\fP option dumps the specified MSR, | 34 | The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34" |
| 39 | in addition to the usual frequency and idle statistics. | 35 | .PP |
| 36 | The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter. | ||
| 37 | .PP | ||
| 38 | The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter. | ||
| 39 | .PP | ||
| 40 | The \fB-m MSR#\fP option includes the the specified 32-bit MSR value. | ||
| 41 | .PP | ||
| 42 | The \fB-M MSR#\fP option includes the the specified 64-bit MSR value. | ||
| 40 | .PP | 43 | .PP |
| 41 | The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. | 44 | The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. |
| 42 | The default is 5 seconds. | 45 | The default is 5 seconds. |
| @@ -150,6 +153,29 @@ Note that turbostat reports average GHz of 3.63, while | |||
| 150 | the arithmetic average of the GHz column above is lower. | 153 | the arithmetic average of the GHz column above is lower. |
| 151 | This is a weighted average, where the weight is %c0. ie. it is the total number of | 154 | This is a weighted average, where the weight is %c0. ie. it is the total number of |
| 152 | un-halted cycles elapsed per time divided by the number of CPUs. | 155 | un-halted cycles elapsed per time divided by the number of CPUs. |
| 156 | .SH SMI COUNTING EXAMPLE | ||
| 157 | On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter. | ||
| 158 | Using the -m option, you can display how many SMIs have fired since reset, or if there | ||
| 159 | are SMIs during the measurement interval, you can display the delta using the -d option. | ||
| 160 | .nf | ||
| 161 | [root@x980 ~]# turbostat -m 0x34 | ||
| 162 | cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6 | ||
| 163 | 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55 | ||
| 164 | 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55 | ||
| 165 | 0 6 0.14 1.63 3.38 0x00000056 5.30 | ||
| 166 | 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52 | ||
| 167 | 1 8 0.10 1.65 3.38 0x00000056 18.05 | ||
| 168 | 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50 | ||
| 169 | 2 10 0.10 1.63 3.38 0x00000056 6.93 | ||
| 170 | 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16 | ||
| 171 | 8 7 0.08 1.64 3.38 0x00000056 5.12 | ||
| 172 | 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38 | ||
| 173 | 9 9 0.09 1.68 3.38 0x00000056 9.32 | ||
| 174 | 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23 | ||
| 175 | 10 11 1.72 1.65 3.38 0x00000056 15.05 | ||
| 176 | ^C | ||
| 177 | [root@x980 ~]# | ||
| 178 | .fi | ||
| 153 | .SH NOTES | 179 | .SH NOTES |
| 154 | 180 | ||
| 155 | .B "turbostat " | 181 | .B "turbostat " |
| @@ -165,6 +191,13 @@ may work poorly on Linux-2.6.20 through 2.6.29, | |||
| 165 | as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF | 191 | as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF |
| 166 | in those kernels. | 192 | in those kernels. |
| 167 | 193 | ||
| 194 | If the TSC column does not make sense, then | ||
| 195 | the other numbers will also make no sense. | ||
| 196 | Turbostat is lightweight, and its data collection is not atomic. | ||
| 197 | These issues are usually caused by an extremely short measurement | ||
| 198 | interval (much less than 1 second), or system activity that prevents | ||
| 199 | turbostat from being able to run on all CPUS to quickly collect data. | ||
| 200 | |||
| 168 | The APERF, MPERF MSRs are defined to count non-halted cycles. | 201 | The APERF, MPERF MSRs are defined to count non-halted cycles. |
| 169 | Although it is not guaranteed by the architecture, turbostat assumes | 202 | Although it is not guaranteed by the architecture, turbostat assumes |
| 170 | that they count at TSC rate, which is true on all processors tested to date. | 203 | that they count at TSC rate, which is true on all processors tested to date. |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 861d77190206..2655ae9a3ad8 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
| @@ -35,9 +35,9 @@ | |||
| 35 | #include <ctype.h> | 35 | #include <ctype.h> |
| 36 | #include <sched.h> | 36 | #include <sched.h> |
| 37 | 37 | ||
| 38 | #define MSR_TSC 0x10 | ||
| 39 | #define MSR_NEHALEM_PLATFORM_INFO 0xCE | 38 | #define MSR_NEHALEM_PLATFORM_INFO 0xCE |
| 40 | #define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD | 39 | #define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD |
| 40 | #define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE | ||
| 41 | #define MSR_APERF 0xE8 | 41 | #define MSR_APERF 0xE8 |
| 42 | #define MSR_MPERF 0xE7 | 42 | #define MSR_MPERF 0xE7 |
| 43 | #define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */ | 43 | #define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */ |
| @@ -62,7 +62,11 @@ unsigned int genuine_intel; | |||
| 62 | unsigned int has_invariant_tsc; | 62 | unsigned int has_invariant_tsc; |
| 63 | unsigned int do_nehalem_platform_info; | 63 | unsigned int do_nehalem_platform_info; |
| 64 | unsigned int do_nehalem_turbo_ratio_limit; | 64 | unsigned int do_nehalem_turbo_ratio_limit; |
| 65 | unsigned int extra_msr_offset; | 65 | unsigned int do_ivt_turbo_ratio_limit; |
| 66 | unsigned int extra_msr_offset32; | ||
| 67 | unsigned int extra_msr_offset64; | ||
| 68 | unsigned int extra_delta_offset32; | ||
| 69 | unsigned int extra_delta_offset64; | ||
| 66 | double bclk; | 70 | double bclk; |
| 67 | unsigned int show_pkg; | 71 | unsigned int show_pkg; |
| 68 | unsigned int show_core; | 72 | unsigned int show_core; |
| @@ -83,7 +87,10 @@ struct thread_data { | |||
| 83 | unsigned long long aperf; | 87 | unsigned long long aperf; |
| 84 | unsigned long long mperf; | 88 | unsigned long long mperf; |
| 85 | unsigned long long c1; /* derived */ | 89 | unsigned long long c1; /* derived */ |
| 86 | unsigned long long extra_msr; | 90 | unsigned long long extra_msr64; |
| 91 | unsigned long long extra_delta64; | ||
| 92 | unsigned long long extra_msr32; | ||
| 93 | unsigned long long extra_delta32; | ||
| 87 | unsigned int cpu_id; | 94 | unsigned int cpu_id; |
| 88 | unsigned int flags; | 95 | unsigned int flags; |
| 89 | #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 | 96 | #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 |
| @@ -222,6 +229,14 @@ void print_header(void) | |||
| 222 | if (has_aperf) | 229 | if (has_aperf) |
| 223 | outp += sprintf(outp, " GHz"); | 230 | outp += sprintf(outp, " GHz"); |
| 224 | outp += sprintf(outp, " TSC"); | 231 | outp += sprintf(outp, " TSC"); |
| 232 | if (extra_delta_offset32) | ||
| 233 | outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); | ||
| 234 | if (extra_delta_offset64) | ||
| 235 | outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64); | ||
| 236 | if (extra_msr_offset32) | ||
| 237 | outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); | ||
| 238 | if (extra_msr_offset64) | ||
| 239 | outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); | ||
| 225 | if (do_nhm_cstates) | 240 | if (do_nhm_cstates) |
| 226 | outp += sprintf(outp, " %%c1"); | 241 | outp += sprintf(outp, " %%c1"); |
| 227 | if (do_nhm_cstates) | 242 | if (do_nhm_cstates) |
| @@ -238,8 +253,6 @@ void print_header(void) | |||
| 238 | outp += sprintf(outp, " %%pc6"); | 253 | outp += sprintf(outp, " %%pc6"); |
| 239 | if (do_snb_cstates) | 254 | if (do_snb_cstates) |
| 240 | outp += sprintf(outp, " %%pc7"); | 255 | outp += sprintf(outp, " %%pc7"); |
| 241 | if (extra_msr_offset) | ||
| 242 | outp += sprintf(outp, " MSR 0x%x ", extra_msr_offset); | ||
| 243 | 256 | ||
| 244 | outp += sprintf(outp, "\n"); | 257 | outp += sprintf(outp, "\n"); |
| 245 | } | 258 | } |
| @@ -255,8 +268,14 @@ int dump_counters(struct thread_data *t, struct core_data *c, | |||
| 255 | fprintf(stderr, "aperf: %016llX\n", t->aperf); | 268 | fprintf(stderr, "aperf: %016llX\n", t->aperf); |
| 256 | fprintf(stderr, "mperf: %016llX\n", t->mperf); | 269 | fprintf(stderr, "mperf: %016llX\n", t->mperf); |
| 257 | fprintf(stderr, "c1: %016llX\n", t->c1); | 270 | fprintf(stderr, "c1: %016llX\n", t->c1); |
| 271 | fprintf(stderr, "msr0x%x: %08llX\n", | ||
| 272 | extra_delta_offset32, t->extra_delta32); | ||
| 258 | fprintf(stderr, "msr0x%x: %016llX\n", | 273 | fprintf(stderr, "msr0x%x: %016llX\n", |
| 259 | extra_msr_offset, t->extra_msr); | 274 | extra_delta_offset64, t->extra_delta64); |
| 275 | fprintf(stderr, "msr0x%x: %08llX\n", | ||
| 276 | extra_msr_offset32, t->extra_msr32); | ||
| 277 | fprintf(stderr, "msr0x%x: %016llX\n", | ||
| 278 | extra_msr_offset64, t->extra_msr64); | ||
| 260 | } | 279 | } |
| 261 | 280 | ||
| 262 | if (c) { | 281 | if (c) { |
| @@ -360,6 +379,21 @@ int format_counters(struct thread_data *t, struct core_data *c, | |||
| 360 | /* TSC */ | 379 | /* TSC */ |
| 361 | outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); | 380 | outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); |
| 362 | 381 | ||
| 382 | /* delta */ | ||
| 383 | if (extra_delta_offset32) | ||
| 384 | outp += sprintf(outp, " %11llu", t->extra_delta32); | ||
| 385 | |||
| 386 | /* DELTA */ | ||
| 387 | if (extra_delta_offset64) | ||
| 388 | outp += sprintf(outp, " %11llu", t->extra_delta64); | ||
| 389 | /* msr */ | ||
| 390 | if (extra_msr_offset32) | ||
| 391 | outp += sprintf(outp, " 0x%08llx", t->extra_msr32); | ||
| 392 | |||
| 393 | /* MSR */ | ||
| 394 | if (extra_msr_offset64) | ||
| 395 | outp += sprintf(outp, " 0x%016llx", t->extra_msr64); | ||
| 396 | |||
| 363 | if (do_nhm_cstates) { | 397 | if (do_nhm_cstates) { |
| 364 | if (!skip_c1) | 398 | if (!skip_c1) |
| 365 | outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); | 399 | outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); |
| @@ -391,8 +425,6 @@ int format_counters(struct thread_data *t, struct core_data *c, | |||
| 391 | if (do_snb_cstates) | 425 | if (do_snb_cstates) |
| 392 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); | 426 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); |
| 393 | done: | 427 | done: |
| 394 | if (extra_msr_offset) | ||
| 395 | outp += sprintf(outp, " 0x%016llx", t->extra_msr); | ||
| 396 | outp += sprintf(outp, "\n"); | 428 | outp += sprintf(outp, "\n"); |
| 397 | 429 | ||
| 398 | return 0; | 430 | return 0; |
| @@ -502,10 +534,16 @@ delta_thread(struct thread_data *new, struct thread_data *old, | |||
| 502 | old->mperf = 1; /* divide by 0 protection */ | 534 | old->mperf = 1; /* divide by 0 protection */ |
| 503 | } | 535 | } |
| 504 | 536 | ||
| 537 | old->extra_delta32 = new->extra_delta32 - old->extra_delta32; | ||
| 538 | old->extra_delta32 &= 0xFFFFFFFF; | ||
| 539 | |||
| 540 | old->extra_delta64 = new->extra_delta64 - old->extra_delta64; | ||
| 541 | |||
| 505 | /* | 542 | /* |
| 506 | * for "extra msr", just copy the latest w/o subtracting | 543 | * Extra MSR is just a snapshot, simply copy latest w/o subtracting |
| 507 | */ | 544 | */ |
| 508 | old->extra_msr = new->extra_msr; | 545 | old->extra_msr32 = new->extra_msr32; |
| 546 | old->extra_msr64 = new->extra_msr64; | ||
| 509 | } | 547 | } |
| 510 | 548 | ||
| 511 | int delta_cpu(struct thread_data *t, struct core_data *c, | 549 | int delta_cpu(struct thread_data *t, struct core_data *c, |
| @@ -533,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data | |||
| 533 | t->mperf = 0; | 571 | t->mperf = 0; |
| 534 | t->c1 = 0; | 572 | t->c1 = 0; |
| 535 | 573 | ||
| 574 | t->extra_delta32 = 0; | ||
| 575 | t->extra_delta64 = 0; | ||
| 576 | |||
| 536 | /* tells format_counters to dump all fields from this set */ | 577 | /* tells format_counters to dump all fields from this set */ |
| 537 | t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; | 578 | t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; |
| 538 | 579 | ||
| @@ -553,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c, | |||
| 553 | average.threads.mperf += t->mperf; | 594 | average.threads.mperf += t->mperf; |
| 554 | average.threads.c1 += t->c1; | 595 | average.threads.c1 += t->c1; |
| 555 | 596 | ||
| 597 | average.threads.extra_delta32 += t->extra_delta32; | ||
| 598 | average.threads.extra_delta64 += t->extra_delta64; | ||
| 599 | |||
| 556 | /* sum per-core values only for 1st thread in core */ | 600 | /* sum per-core values only for 1st thread in core */ |
| 557 | if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) | 601 | if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) |
| 558 | return 0; | 602 | return 0; |
| @@ -588,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c, | |||
| 588 | average.threads.mperf /= topo.num_cpus; | 632 | average.threads.mperf /= topo.num_cpus; |
| 589 | average.threads.c1 /= topo.num_cpus; | 633 | average.threads.c1 /= topo.num_cpus; |
| 590 | 634 | ||
| 635 | average.threads.extra_delta32 /= topo.num_cpus; | ||
| 636 | average.threads.extra_delta32 &= 0xFFFFFFFF; | ||
| 637 | |||
| 638 | average.threads.extra_delta64 /= topo.num_cpus; | ||
| 639 | |||
| 591 | average.cores.c3 /= topo.num_cores; | 640 | average.cores.c3 /= topo.num_cores; |
| 592 | average.cores.c6 /= topo.num_cores; | 641 | average.cores.c6 /= topo.num_cores; |
| 593 | average.cores.c7 /= topo.num_cores; | 642 | average.cores.c7 /= topo.num_cores; |
| @@ -629,8 +678,24 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) | |||
| 629 | return -4; | 678 | return -4; |
| 630 | } | 679 | } |
| 631 | 680 | ||
| 632 | if (extra_msr_offset) | 681 | if (extra_delta_offset32) { |
| 633 | if (get_msr(cpu, extra_msr_offset, &t->extra_msr)) | 682 | if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32)) |
| 683 | return -5; | ||
| 684 | t->extra_delta32 &= 0xFFFFFFFF; | ||
| 685 | } | ||
| 686 | |||
| 687 | if (extra_delta_offset64) | ||
| 688 | if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64)) | ||
| 689 | return -5; | ||
| 690 | |||
| 691 | if (extra_msr_offset32) { | ||
| 692 | if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32)) | ||
| 693 | return -5; | ||
| 694 | t->extra_msr32 &= 0xFFFFFFFF; | ||
| 695 | } | ||
| 696 | |||
| 697 | if (extra_msr_offset64) | ||
| 698 | if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64)) | ||
| 634 | return -5; | 699 | return -5; |
| 635 | 700 | ||
| 636 | /* collect core counters only for 1st thread in core */ | 701 | /* collect core counters only for 1st thread in core */ |
| @@ -677,6 +742,9 @@ void print_verbose_header(void) | |||
| 677 | 742 | ||
| 678 | get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); | 743 | get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); |
| 679 | 744 | ||
| 745 | if (verbose > 1) | ||
| 746 | fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); | ||
| 747 | |||
| 680 | ratio = (msr >> 40) & 0xFF; | 748 | ratio = (msr >> 40) & 0xFF; |
| 681 | fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", | 749 | fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", |
| 682 | ratio, bclk, ratio * bclk); | 750 | ratio, bclk, ratio * bclk); |
| @@ -685,14 +753,84 @@ void print_verbose_header(void) | |||
| 685 | fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", | 753 | fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", |
| 686 | ratio, bclk, ratio * bclk); | 754 | ratio, bclk, ratio * bclk); |
| 687 | 755 | ||
| 756 | if (!do_ivt_turbo_ratio_limit) | ||
| 757 | goto print_nhm_turbo_ratio_limits; | ||
| 758 | |||
| 759 | get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr); | ||
| 760 | |||
| 688 | if (verbose > 1) | 761 | if (verbose > 1) |
| 689 | fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); | 762 | fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr); |
| 763 | |||
| 764 | ratio = (msr >> 56) & 0xFF; | ||
| 765 | if (ratio) | ||
| 766 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n", | ||
| 767 | ratio, bclk, ratio * bclk); | ||
| 768 | |||
| 769 | ratio = (msr >> 48) & 0xFF; | ||
| 770 | if (ratio) | ||
| 771 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n", | ||
| 772 | ratio, bclk, ratio * bclk); | ||
| 773 | |||
| 774 | ratio = (msr >> 40) & 0xFF; | ||
| 775 | if (ratio) | ||
| 776 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n", | ||
| 777 | ratio, bclk, ratio * bclk); | ||
| 778 | |||
| 779 | ratio = (msr >> 32) & 0xFF; | ||
| 780 | if (ratio) | ||
| 781 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n", | ||
| 782 | ratio, bclk, ratio * bclk); | ||
| 783 | |||
| 784 | ratio = (msr >> 24) & 0xFF; | ||
| 785 | if (ratio) | ||
| 786 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n", | ||
| 787 | ratio, bclk, ratio * bclk); | ||
| 788 | |||
| 789 | ratio = (msr >> 16) & 0xFF; | ||
| 790 | if (ratio) | ||
| 791 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n", | ||
| 792 | ratio, bclk, ratio * bclk); | ||
| 793 | |||
| 794 | ratio = (msr >> 8) & 0xFF; | ||
| 795 | if (ratio) | ||
| 796 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n", | ||
| 797 | ratio, bclk, ratio * bclk); | ||
| 798 | |||
| 799 | ratio = (msr >> 0) & 0xFF; | ||
| 800 | if (ratio) | ||
| 801 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", | ||
| 802 | ratio, bclk, ratio * bclk); | ||
| 803 | |||
| 804 | print_nhm_turbo_ratio_limits: | ||
| 690 | 805 | ||
| 691 | if (!do_nehalem_turbo_ratio_limit) | 806 | if (!do_nehalem_turbo_ratio_limit) |
| 692 | return; | 807 | return; |
| 693 | 808 | ||
| 694 | get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); | 809 | get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); |
| 695 | 810 | ||
| 811 | if (verbose > 1) | ||
| 812 | fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr); | ||
| 813 | |||
| 814 | ratio = (msr >> 56) & 0xFF; | ||
| 815 | if (ratio) | ||
| 816 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n", | ||
| 817 | ratio, bclk, ratio * bclk); | ||
| 818 | |||
| 819 | ratio = (msr >> 48) & 0xFF; | ||
| 820 | if (ratio) | ||
| 821 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n", | ||
| 822 | ratio, bclk, ratio * bclk); | ||
| 823 | |||
| 824 | ratio = (msr >> 40) & 0xFF; | ||
| 825 | if (ratio) | ||
| 826 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n", | ||
| 827 | ratio, bclk, ratio * bclk); | ||
| 828 | |||
| 829 | ratio = (msr >> 32) & 0xFF; | ||
| 830 | if (ratio) | ||
| 831 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n", | ||
| 832 | ratio, bclk, ratio * bclk); | ||
| 833 | |||
| 696 | ratio = (msr >> 24) & 0xFF; | 834 | ratio = (msr >> 24) & 0xFF; |
| 697 | if (ratio) | 835 | if (ratio) |
| 698 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", | 836 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", |
| @@ -712,7 +850,6 @@ void print_verbose_header(void) | |||
| 712 | if (ratio) | 850 | if (ratio) |
| 713 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", | 851 | fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", |
| 714 | ratio, bclk, ratio * bclk); | 852 | ratio, bclk, ratio * bclk); |
| 715 | |||
| 716 | } | 853 | } |
| 717 | 854 | ||
| 718 | void free_all_buffers(void) | 855 | void free_all_buffers(void) |
| @@ -1038,7 +1175,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) | |||
| 1038 | case 0x2A: /* SNB */ | 1175 | case 0x2A: /* SNB */ |
| 1039 | case 0x2D: /* SNB Xeon */ | 1176 | case 0x2D: /* SNB Xeon */ |
| 1040 | case 0x3A: /* IVB */ | 1177 | case 0x3A: /* IVB */ |
| 1041 | case 0x3D: /* IVB Xeon */ | 1178 | case 0x3E: /* IVB Xeon */ |
| 1042 | return 1; | 1179 | return 1; |
| 1043 | case 0x2E: /* Nehalem-EX Xeon - Beckton */ | 1180 | case 0x2E: /* Nehalem-EX Xeon - Beckton */ |
| 1044 | case 0x2F: /* Westmere-EX Xeon - Eagleton */ | 1181 | case 0x2F: /* Westmere-EX Xeon - Eagleton */ |
| @@ -1046,6 +1183,22 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) | |||
| 1046 | return 0; | 1183 | return 0; |
| 1047 | } | 1184 | } |
| 1048 | } | 1185 | } |
| 1186 | int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) | ||
| 1187 | { | ||
| 1188 | if (!genuine_intel) | ||
| 1189 | return 0; | ||
| 1190 | |||
| 1191 | if (family != 6) | ||
| 1192 | return 0; | ||
| 1193 | |||
| 1194 | switch (model) { | ||
| 1195 | case 0x3E: /* IVB Xeon */ | ||
| 1196 | return 1; | ||
| 1197 | default: | ||
| 1198 | return 0; | ||
| 1199 | } | ||
| 1200 | } | ||
| 1201 | |||
| 1049 | 1202 | ||
| 1050 | int is_snb(unsigned int family, unsigned int model) | 1203 | int is_snb(unsigned int family, unsigned int model) |
| 1051 | { | 1204 | { |
| @@ -1056,7 +1209,7 @@ int is_snb(unsigned int family, unsigned int model) | |||
| 1056 | case 0x2A: | 1209 | case 0x2A: |
| 1057 | case 0x2D: | 1210 | case 0x2D: |
| 1058 | case 0x3A: /* IVB */ | 1211 | case 0x3A: /* IVB */ |
| 1059 | case 0x3D: /* IVB Xeon */ | 1212 | case 0x3E: /* IVB Xeon */ |
| 1060 | return 1; | 1213 | return 1; |
| 1061 | } | 1214 | } |
| 1062 | return 0; | 1215 | return 0; |
| @@ -1145,12 +1298,13 @@ void check_cpuid() | |||
| 1145 | bclk = discover_bclk(family, model); | 1298 | bclk = discover_bclk(family, model); |
| 1146 | 1299 | ||
| 1147 | do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); | 1300 | do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); |
| 1301 | do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model); | ||
| 1148 | } | 1302 | } |
| 1149 | 1303 | ||
| 1150 | 1304 | ||
| 1151 | void usage() | 1305 | void usage() |
| 1152 | { | 1306 | { |
| 1153 | fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n", | 1307 | fprintf(stderr, "%s: [-v][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", |
| 1154 | progname); | 1308 | progname); |
| 1155 | exit(1); | 1309 | exit(1); |
| 1156 | } | 1310 | } |
| @@ -1440,15 +1594,15 @@ void cmdline(int argc, char **argv) | |||
| 1440 | 1594 | ||
| 1441 | progname = argv[0]; | 1595 | progname = argv[0]; |
| 1442 | 1596 | ||
| 1443 | while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) { | 1597 | while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) { |
| 1444 | switch (opt) { | 1598 | switch (opt) { |
| 1445 | case 'c': | 1599 | case 'p': |
| 1446 | show_core_only++; | 1600 | show_core_only++; |
| 1447 | break; | 1601 | break; |
| 1448 | case 'p': | 1602 | case 'P': |
| 1449 | show_pkg_only++; | 1603 | show_pkg_only++; |
| 1450 | break; | 1604 | break; |
| 1451 | case 's': | 1605 | case 'S': |
| 1452 | summary_only++; | 1606 | summary_only++; |
| 1453 | break; | 1607 | break; |
| 1454 | case 'v': | 1608 | case 'v': |
| @@ -1457,10 +1611,20 @@ void cmdline(int argc, char **argv) | |||
| 1457 | case 'i': | 1611 | case 'i': |
| 1458 | interval_sec = atoi(optarg); | 1612 | interval_sec = atoi(optarg); |
| 1459 | break; | 1613 | break; |
| 1614 | case 'c': | ||
| 1615 | sscanf(optarg, "%x", &extra_delta_offset32); | ||
| 1616 | break; | ||
| 1617 | case 's': | ||
| 1618 | extra_delta_offset32 = 0x34; /* SMI counter */ | ||
| 1619 | break; | ||
| 1620 | case 'C': | ||
| 1621 | sscanf(optarg, "%x", &extra_delta_offset64); | ||
| 1622 | break; | ||
| 1623 | case 'm': | ||
| 1624 | sscanf(optarg, "%x", &extra_msr_offset32); | ||
| 1625 | break; | ||
| 1460 | case 'M': | 1626 | case 'M': |
| 1461 | sscanf(optarg, "%x", &extra_msr_offset); | 1627 | sscanf(optarg, "%x", &extra_msr_offset64); |
| 1462 | if (verbose > 1) | ||
| 1463 | fprintf(stderr, "MSR 0x%X\n", extra_msr_offset); | ||
| 1464 | break; | 1628 | break; |
| 1465 | default: | 1629 | default: |
| 1466 | usage(); | 1630 | usage(); |
| @@ -1473,7 +1637,7 @@ int main(int argc, char **argv) | |||
| 1473 | cmdline(argc, argv); | 1637 | cmdline(argc, argv); |
| 1474 | 1638 | ||
| 1475 | if (verbose > 1) | 1639 | if (verbose > 1) |
| 1476 | fprintf(stderr, "turbostat v2.0 May 16, 2012" | 1640 | fprintf(stderr, "turbostat v2.1 October 6, 2012" |
| 1477 | " - Len Brown <lenb@kernel.org>\n"); | 1641 | " - Len Brown <lenb@kernel.org>\n"); |
| 1478 | 1642 | ||
| 1479 | turbostat_init(); | 1643 | turbostat_init(); |
