diff options
27 files changed, 435 insertions, 360 deletions
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 01c6c3d8a7e3..64b3f146e4b0 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
| @@ -503,7 +503,7 @@ generate input device EV_KEY events. | |||
| 503 | In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW | 503 | In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW |
| 504 | events for switches: | 504 | events for switches: |
| 505 | 505 | ||
| 506 | SW_RADIO T60 and later hardare rfkill rocker switch | 506 | SW_RFKILL_ALL T60 and later hardare rfkill rocker switch |
| 507 | SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A | 507 | SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A |
| 508 | 508 | ||
| 509 | Non hot-key ACPI HKEY event map: | 509 | Non hot-key ACPI HKEY event map: |
diff --git a/MAINTAINERS b/MAINTAINERS index e3560df4608e..9d4304266043 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -228,21 +228,21 @@ ACPI BATTERY DRIVERS | |||
| 228 | P: Alexey Starikovskiy | 228 | P: Alexey Starikovskiy |
| 229 | M: astarikovskiy@suse.de | 229 | M: astarikovskiy@suse.de |
| 230 | L: linux-acpi@vger.kernel.org | 230 | L: linux-acpi@vger.kernel.org |
| 231 | W: http://acpi.sourceforge.net/ | 231 | W: http://www.lesswatts.org/projects/acpi/ |
| 232 | S: Supported | 232 | S: Supported |
| 233 | 233 | ||
| 234 | ACPI EC DRIVER | 234 | ACPI EC DRIVER |
| 235 | P: Alexey Starikovskiy | 235 | P: Alexey Starikovskiy |
| 236 | M: astarikovskiy@suse.de | 236 | M: astarikovskiy@suse.de |
| 237 | L: linux-acpi@vger.kernel.org | 237 | L: linux-acpi@vger.kernel.org |
| 238 | W: http://acpi.sourceforge.net/ | 238 | W: http://www.lesswatts.org/projects/acpi/ |
| 239 | S: Supported | 239 | S: Supported |
| 240 | 240 | ||
| 241 | ACPI FAN DRIVER | 241 | ACPI FAN DRIVER |
| 242 | P: Len Brown | 242 | P: Len Brown |
| 243 | M: len.brown@intel.com | 243 | M: len.brown@intel.com |
| 244 | L: linux-acpi@vger.kernel.org | 244 | L: linux-acpi@vger.kernel.org |
| 245 | W: http://acpi.sourceforge.net/ | 245 | W: http://www.lesswatts.org/projects/acpi/ |
| 246 | S: Supported | 246 | S: Supported |
| 247 | 247 | ||
| 248 | ACPI PCI HOTPLUG DRIVER | 248 | ACPI PCI HOTPLUG DRIVER |
| @@ -255,14 +255,14 @@ ACPI THERMAL DRIVER | |||
| 255 | P: Len Brown | 255 | P: Len Brown |
| 256 | M: len.brown@intel.com | 256 | M: len.brown@intel.com |
| 257 | L: linux-acpi@vger.kernel.org | 257 | L: linux-acpi@vger.kernel.org |
| 258 | W: http://acpi.sourceforge.net/ | 258 | W: http://www.lesswatts.org/projects/acpi/ |
| 259 | S: Supported | 259 | S: Supported |
| 260 | 260 | ||
| 261 | ACPI VIDEO DRIVER | 261 | ACPI VIDEO DRIVER |
| 262 | P: Rui Zhang | 262 | P: Rui Zhang |
| 263 | M: rui.zhang@intel.com | 263 | M: rui.zhang@intel.com |
| 264 | L: linux-acpi@vger.kernel.org | 264 | L: linux-acpi@vger.kernel.org |
| 265 | W: http://acpi.sourceforge.net/ | 265 | W: http://www.lesswatts.org/projects/acpi/ |
| 266 | S: Supported | 266 | S: Supported |
| 267 | 267 | ||
| 268 | ACPI WMI DRIVER | 268 | ACPI WMI DRIVER |
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 853d1f11be00..43687cc60dfb 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
| @@ -465,7 +465,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | |||
| 465 | printk(KERN_ERR | 465 | printk(KERN_ERR |
| 466 | "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", | 466 | "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", |
| 467 | len, slit->header.length); | 467 | len, slit->header.length); |
| 468 | memset(numa_slit, 10, sizeof(numa_slit)); | ||
| 469 | return; | 468 | return; |
| 470 | } | 469 | } |
| 471 | slit_table = slit; | 470 | slit_table = slit; |
| @@ -574,8 +573,14 @@ void __init acpi_numa_arch_fixup(void) | |||
| 574 | printk(KERN_INFO "Number of memory chunks in system = %d\n", | 573 | printk(KERN_INFO "Number of memory chunks in system = %d\n", |
| 575 | num_node_memblks); | 574 | num_node_memblks); |
| 576 | 575 | ||
| 577 | if (!slit_table) | 576 | if (!slit_table) { |
| 577 | for (i = 0; i < MAX_NUMNODES; i++) | ||
| 578 | for (j = 0; j < MAX_NUMNODES; j++) | ||
| 579 | node_distance(i, j) = i == j ? LOCAL_DISTANCE : | ||
| 580 | REMOTE_DISTANCE; | ||
| 578 | return; | 581 | return; |
| 582 | } | ||
| 583 | |||
| 579 | memset(numa_slit, -1, sizeof(numa_slit)); | 584 | memset(numa_slit, -1, sizeof(numa_slit)); |
| 580 | for (i = 0; i < slit_table->locality_count; i++) { | 585 | for (i = 0; i < slit_table->locality_count; i++) { |
| 581 | if (!pxm_bit_test(i)) | 586 | if (!pxm_bit_test(i)) |
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 3890234e5b26..99649dccad28 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
| @@ -97,36 +97,9 @@ static __init inline int srat_disabled(void) | |||
| 97 | return numa_off || acpi_numa < 0; | 97 | return numa_off || acpi_numa < 0; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | /* | ||
| 101 | * A lot of BIOS fill in 10 (= no distance) everywhere. This messes | ||
| 102 | * up the NUMA heuristics which wants the local node to have a smaller | ||
| 103 | * distance than the others. | ||
| 104 | * Do some quick checks here and only use the SLIT if it passes. | ||
| 105 | */ | ||
| 106 | static __init int slit_valid(struct acpi_table_slit *slit) | ||
| 107 | { | ||
| 108 | int i, j; | ||
| 109 | int d = slit->locality_count; | ||
| 110 | for (i = 0; i < d; i++) { | ||
| 111 | for (j = 0; j < d; j++) { | ||
| 112 | u8 val = slit->entry[d*i + j]; | ||
| 113 | if (i == j) { | ||
| 114 | if (val != LOCAL_DISTANCE) | ||
| 115 | return 0; | ||
| 116 | } else if (val <= LOCAL_DISTANCE) | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | return 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Callback for SLIT parsing */ | 100 | /* Callback for SLIT parsing */ |
| 124 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | 101 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) |
| 125 | { | 102 | { |
| 126 | if (!slit_valid(slit)) { | ||
| 127 | printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | acpi_slit = slit; | 103 | acpi_slit = slit; |
| 131 | } | 104 | } |
| 132 | 105 | ||
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index d2fc94161848..26038c2a2a71 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c | |||
| @@ -301,16 +301,20 @@ static int bay_add(acpi_handle handle, int id) | |||
| 301 | */ | 301 | */ |
| 302 | pdev->dev.uevent_suppress = 0; | 302 | pdev->dev.uevent_suppress = 0; |
| 303 | 303 | ||
| 304 | if (acpi_bay_add_fs(new_bay)) { | ||
| 305 | platform_device_unregister(new_bay->pdev); | ||
| 306 | goto bay_add_err; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* register for events on this device */ | 304 | /* register for events on this device */ |
| 310 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 305 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
| 311 | bay_notify, new_bay); | 306 | bay_notify, new_bay); |
| 312 | if (ACPI_FAILURE(status)) { | 307 | if (ACPI_FAILURE(status)) { |
| 313 | printk(KERN_ERR PREFIX "Error installing bay notify handler\n"); | 308 | printk(KERN_INFO PREFIX "Error installing bay notify handler\n"); |
| 309 | platform_device_unregister(new_bay->pdev); | ||
| 310 | goto bay_add_err; | ||
| 311 | } | ||
| 312 | |||
| 313 | if (acpi_bay_add_fs(new_bay)) { | ||
| 314 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
| 315 | bay_notify); | ||
| 316 | platform_device_unregister(new_bay->pdev); | ||
| 317 | goto bay_add_err; | ||
| 314 | } | 318 | } |
| 315 | 319 | ||
| 316 | /* if we are on a dock station, we should register for dock | 320 | /* if we are on a dock station, we should register for dock |
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index c78078315be9..f988a5e7d2b4 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c | |||
| @@ -450,10 +450,6 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
| 450 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 450 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | if (!arg) { | ||
| 454 | return_ACPI_STATUS(AE_AML_NO_OPERAND); | ||
| 455 | } | ||
| 456 | |||
| 457 | /* Creating new namespace node(s), should not already exist */ | 453 | /* Creating new namespace node(s), should not already exist */ |
| 458 | 454 | ||
| 459 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | 455 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
| @@ -467,6 +463,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
| 467 | 463 | ||
| 468 | /* | 464 | /* |
| 469 | * Walk the list of entries in the field_list | 465 | * Walk the list of entries in the field_list |
| 466 | * Note: field_list can be of zero length. In this case, Arg will be NULL. | ||
| 470 | */ | 467 | */ |
| 471 | while (arg) { | 468 | while (arg) { |
| 472 | /* | 469 | /* |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index fa44fb96fc34..96c542f7fded 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
| @@ -834,7 +834,7 @@ static int dock_add(acpi_handle handle) | |||
| 834 | goto dock_add_err; | 834 | goto dock_add_err; |
| 835 | } | 835 | } |
| 836 | 836 | ||
| 837 | printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION); | 837 | printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION); |
| 838 | 838 | ||
| 839 | return 0; | 839 | return 0; |
| 840 | 840 | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 0924992187e8..5622aee996b2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -194,7 +194,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | |||
| 194 | while (time_before(jiffies, delay)) { | 194 | while (time_before(jiffies, delay)) { |
| 195 | if (acpi_ec_check_status(ec, event)) | 195 | if (acpi_ec_check_status(ec, event)) |
| 196 | return 0; | 196 | return 0; |
| 197 | udelay(ACPI_EC_UDELAY); | 197 | msleep(1); |
| 198 | } | 198 | } |
| 199 | } | 199 | } |
| 200 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", | 200 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", |
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 24da921d13e3..39d742190584 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
| @@ -375,9 +375,15 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
| 375 | goto cleanup; | 375 | goto cleanup; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | /* | ||
| 379 | * Add the table to the namespace. | ||
| 380 | * | ||
| 381 | * Note: We load the table objects relative to the root of the namespace. | ||
| 382 | * This appears to go against the ACPI specification, but we do it for | ||
| 383 | * compatibility with other ACPI implementations. | ||
| 384 | */ | ||
| 378 | status = | 385 | status = |
| 379 | acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, | 386 | acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); |
| 380 | &ddb_handle); | ||
| 381 | if (ACPI_FAILURE(status)) { | 387 | if (ACPI_FAILURE(status)) { |
| 382 | 388 | ||
| 383 | /* On error, table_ptr was deallocated above */ | 389 | /* On error, table_ptr was deallocated above */ |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 06f8634fe58b..2808dc60fd67 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -272,6 +272,12 @@ static u32 rtc_handler(void *context) | |||
| 272 | static inline void rtc_wake_setup(void) | 272 | static inline void rtc_wake_setup(void) |
| 273 | { | 273 | { |
| 274 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); | 274 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); |
| 275 | /* | ||
| 276 | * After the RTC handler is installed, the Fixed_RTC event should | ||
| 277 | * be disabled. Only when the RTC alarm is set will it be enabled. | ||
| 278 | */ | ||
| 279 | acpi_clear_event(ACPI_EVENT_RTC); | ||
| 280 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
| 275 | } | 281 | } |
| 276 | 282 | ||
| 277 | static void rtc_wake_on(struct device *dev) | 283 | static void rtc_wake_on(struct device *dev) |
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index d9937e05ec6a..dba3cfbe8cba 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c | |||
| @@ -223,15 +223,17 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | |||
| 223 | break; | 223 | break; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | /* Set the system indicators to show the desired sleep state. */ | 226 | /* |
| 227 | 227 | * Set the system indicators to show the desired sleep state. | |
| 228 | * _SST is an optional method (return no error if not found) | ||
| 229 | */ | ||
| 228 | status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | 230 | status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); |
| 229 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 231 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
| 230 | ACPI_EXCEPTION((AE_INFO, status, | 232 | ACPI_EXCEPTION((AE_INFO, status, |
| 231 | "While executing method _SST")); | 233 | "While executing method _SST")); |
| 232 | } | 234 | } |
| 233 | 235 | ||
| 234 | return_ACPI_STATUS(status); | 236 | return_ACPI_STATUS(AE_OK); |
| 235 | } | 237 | } |
| 236 | 238 | ||
| 237 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) | 239 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 5d59cb33b1a5..658e5f3abae0 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
| @@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) | |||
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | /* | ||
| 144 | * A lot of BIOS fill in 10 (= no distance) everywhere. This messes | ||
| 145 | * up the NUMA heuristics which wants the local node to have a smaller | ||
| 146 | * distance than the others. | ||
| 147 | * Do some quick checks here and only use the SLIT if it passes. | ||
| 148 | */ | ||
| 149 | static __init int slit_valid(struct acpi_table_slit *slit) | ||
| 150 | { | ||
| 151 | int i, j; | ||
| 152 | int d = slit->locality_count; | ||
| 153 | for (i = 0; i < d; i++) { | ||
| 154 | for (j = 0; j < d; j++) { | ||
| 155 | u8 val = slit->entry[d*i + j]; | ||
| 156 | if (i == j) { | ||
| 157 | if (val != LOCAL_DISTANCE) | ||
| 158 | return 0; | ||
| 159 | } else if (val <= LOCAL_DISTANCE) | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | return 1; | ||
| 164 | } | ||
| 165 | |||
| 143 | static int __init acpi_parse_slit(struct acpi_table_header *table) | 166 | static int __init acpi_parse_slit(struct acpi_table_header *table) |
| 144 | { | 167 | { |
| 145 | struct acpi_table_slit *slit; | 168 | struct acpi_table_slit *slit; |
| 146 | u32 localities; | ||
| 147 | 169 | ||
| 148 | if (!table) | 170 | if (!table) |
| 149 | return -EINVAL; | 171 | return -EINVAL; |
| 150 | 172 | ||
| 151 | slit = (struct acpi_table_slit *)table; | 173 | slit = (struct acpi_table_slit *)table; |
| 152 | 174 | ||
| 153 | /* downcast just for %llu vs %lu for i386/ia64 */ | 175 | if (!slit_valid(slit)) { |
| 154 | localities = (u32) slit->locality_count; | 176 | printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); |
| 155 | 177 | return -EINVAL; | |
| 178 | } | ||
| 156 | acpi_numa_slit_init(slit); | 179 | acpi_numa_slit_init(slit); |
| 157 | 180 | ||
| 158 | return 0; | 181 | return 0; |
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index f1e8bf65e24e..e94463778845 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c | |||
| @@ -268,7 +268,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, | |||
| 268 | */ | 268 | */ |
| 269 | if (ACPI_SUCCESS(status) && | 269 | if (ACPI_SUCCESS(status) && |
| 270 | possible_method_call && (node->type == ACPI_TYPE_METHOD)) { | 270 | possible_method_call && (node->type == ACPI_TYPE_METHOD)) { |
| 271 | if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { | 271 | if (walk_state->opcode == AML_UNLOAD_OP) { |
| 272 | /* | 272 | /* |
| 273 | * acpi_ps_get_next_namestring has increased the AML pointer, | 273 | * acpi_ps_get_next_namestring has increased the AML pointer, |
| 274 | * so we need to restore the saved AML pointer for method call. | 274 | * so we need to restore the saved AML pointer for method call. |
| @@ -691,7 +691,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, | |||
| 691 | 691 | ||
| 692 | /* To support super_name arg of Unload */ | 692 | /* To support super_name arg of Unload */ |
| 693 | 693 | ||
| 694 | if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { | 694 | if (walk_state->opcode == AML_UNLOAD_OP) { |
| 695 | status = | 695 | status = |
| 696 | acpi_ps_get_next_namepath(walk_state, | 696 | acpi_ps_get_next_namepath(walk_state, |
| 697 | parser_state, arg, | 697 | parser_state, arg, |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 386e5aa48834..9dd0fa93b9e1 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -86,7 +86,6 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); | |||
| 86 | static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); | 86 | static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); |
| 87 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); | 87 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); |
| 88 | static int acpi_processor_handle_eject(struct acpi_processor *pr); | 88 | static int acpi_processor_handle_eject(struct acpi_processor *pr); |
| 89 | extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); | ||
| 90 | 89 | ||
| 91 | 90 | ||
| 92 | static const struct acpi_device_id processor_device_ids[] = { | 91 | static const struct acpi_device_id processor_device_ids[] = { |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2dd2c1f3a01c..556ee1585192 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) | |||
| 1669 | return -EINVAL; | 1669 | return -EINVAL; |
| 1670 | } | 1670 | } |
| 1671 | 1671 | ||
| 1672 | dev->cpu = pr->id; | ||
| 1672 | for (i = 0; i < CPUIDLE_STATE_MAX; i++) { | 1673 | for (i = 0; i < CPUIDLE_STATE_MAX; i++) { |
| 1673 | dev->states[i].name[0] = '\0'; | 1674 | dev->states[i].name[0] = '\0'; |
| 1674 | dev->states[i].desc[0] = '\0'; | 1675 | dev->states[i].desc[0] = '\0'; |
| @@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) | |||
| 1738 | 1739 | ||
| 1739 | int acpi_processor_cst_has_changed(struct acpi_processor *pr) | 1740 | int acpi_processor_cst_has_changed(struct acpi_processor *pr) |
| 1740 | { | 1741 | { |
| 1741 | int ret; | 1742 | int ret = 0; |
| 1742 | 1743 | ||
| 1743 | if (boot_option_idle_override) | 1744 | if (boot_option_idle_override) |
| 1744 | return 0; | 1745 | return 0; |
| @@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
| 1756 | cpuidle_pause_and_lock(); | 1757 | cpuidle_pause_and_lock(); |
| 1757 | cpuidle_disable_device(&pr->power.dev); | 1758 | cpuidle_disable_device(&pr->power.dev); |
| 1758 | acpi_processor_get_power_info(pr); | 1759 | acpi_processor_get_power_info(pr); |
| 1759 | acpi_processor_setup_cpuidle(pr); | 1760 | if (pr->flags.power) { |
| 1760 | ret = cpuidle_enable_device(&pr->power.dev); | 1761 | acpi_processor_setup_cpuidle(pr); |
| 1762 | ret = cpuidle_enable_device(&pr->power.dev); | ||
| 1763 | } | ||
| 1761 | cpuidle_resume_and_unlock(); | 1764 | cpuidle_resume_and_unlock(); |
| 1762 | 1765 | ||
| 1763 | return ret; | 1766 | return ret; |
| @@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
| 1813 | if (pr->flags.power) { | 1816 | if (pr->flags.power) { |
| 1814 | #ifdef CONFIG_CPU_IDLE | 1817 | #ifdef CONFIG_CPU_IDLE |
| 1815 | acpi_processor_setup_cpuidle(pr); | 1818 | acpi_processor_setup_cpuidle(pr); |
| 1816 | pr->power.dev.cpu = pr->id; | ||
| 1817 | if (cpuidle_register_device(&pr->power.dev)) | 1819 | if (cpuidle_register_device(&pr->power.dev)) |
| 1818 | return -EIO; | 1820 | return -EIO; |
| 1819 | #endif | 1821 | #endif |
| @@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr, | |||
| 1850 | return 0; | 1852 | return 0; |
| 1851 | 1853 | ||
| 1852 | #ifdef CONFIG_CPU_IDLE | 1854 | #ifdef CONFIG_CPU_IDLE |
| 1853 | if (pr->flags.power) | 1855 | cpuidle_unregister_device(&pr->power.dev); |
| 1854 | cpuidle_unregister_device(&pr->power.dev); | ||
| 1855 | #endif | 1856 | #endif |
| 1856 | pr->flags.power_setup_done = 0; | 1857 | pr->flags.power_setup_done = 0; |
| 1857 | 1858 | ||
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 8a5fe8710513..224c57c03381 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
| @@ -495,6 +495,12 @@ static int __init acpi_sleep_proc_init(void) | |||
| 495 | acpi_root_dir, &acpi_system_alarm_fops); | 495 | acpi_root_dir, &acpi_system_alarm_fops); |
| 496 | 496 | ||
| 497 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); | 497 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); |
| 498 | /* | ||
| 499 | * Disable the RTC event after installing RTC handler. | ||
| 500 | * Only when RTC alarm is set will it be enabled. | ||
| 501 | */ | ||
| 502 | acpi_clear_event(ACPI_EVENT_RTC); | ||
| 503 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
| 498 | #endif /* HAVE_ACPI_LEGACY_ALARM */ | 504 | #endif /* HAVE_ACPI_LEGACY_ALARM */ |
| 499 | 505 | ||
| 500 | /* 'wakeup device' [R/W] */ | 506 | /* 'wakeup device' [R/W] */ |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 769f24855eb6..5bd2dec9a7ac 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
| @@ -77,7 +77,6 @@ static ssize_t acpi_table_show(struct kobject *kobj, | |||
| 77 | container_of(bin_attr, struct acpi_table_attr, attr); | 77 | container_of(bin_attr, struct acpi_table_attr, attr); |
| 78 | struct acpi_table_header *table_header = NULL; | 78 | struct acpi_table_header *table_header = NULL; |
| 79 | acpi_status status; | 79 | acpi_status status; |
| 80 | ssize_t ret_count = count; | ||
| 81 | 80 | ||
| 82 | status = | 81 | status = |
| 83 | acpi_get_table(table_attr->name, table_attr->instance, | 82 | acpi_get_table(table_attr->name, table_attr->instance, |
| @@ -85,18 +84,8 @@ static ssize_t acpi_table_show(struct kobject *kobj, | |||
| 85 | if (ACPI_FAILURE(status)) | 84 | if (ACPI_FAILURE(status)) |
| 86 | return -ENODEV; | 85 | return -ENODEV; |
| 87 | 86 | ||
| 88 | if (offset >= table_header->length) { | 87 | return memory_read_from_buffer(buf, count, &offset, |
| 89 | ret_count = 0; | 88 | table_header, table_header->length); |
| 90 | goto end; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (offset + ret_count > table_header->length) | ||
| 94 | ret_count = table_header->length - offset; | ||
| 95 | |||
| 96 | memcpy(buf, ((char *)table_header) + offset, ret_count); | ||
| 97 | |||
| 98 | end: | ||
| 99 | return ret_count; | ||
| 100 | } | 89 | } |
| 101 | 90 | ||
| 102 | static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | 91 | static void acpi_table_attr_init(struct acpi_table_attr *table_attr, |
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 402f93e1ff20..5336ce88f89f 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c | |||
| @@ -123,24 +123,13 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, | |||
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | /* The table must be either an SSDT or a PSDT or an OEMx */ | 126 | /* |
| 127 | 127 | * Originally, we checked the table signature for "SSDT" or "PSDT" here. | |
| 128 | if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&& | 128 | * Next, we added support for OEMx tables, signature "OEM". |
| 129 | !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&& | 129 | * Valid tables were encountered with a null signature, so we've just |
| 130 | strncmp(table_desc->pointer->signature, "OEM", 3)) { | 130 | * given up on validating the signature, since it seems to be a waste |
| 131 | /* Check for a printable name */ | 131 | * of code. The original code was removed (05/2008). |
| 132 | if (acpi_ut_valid_acpi_name( | 132 | */ |
| 133 | *(u32 *) table_desc->pointer->signature)) { | ||
| 134 | ACPI_ERROR((AE_INFO, "Table has invalid signature " | ||
| 135 | "[%4.4s], must be SSDT or PSDT", | ||
| 136 | table_desc->pointer->signature)); | ||
| 137 | } else { | ||
| 138 | ACPI_ERROR((AE_INFO, "Table has invalid signature " | ||
| 139 | "(0x%8.8X), must be SSDT or PSDT", | ||
| 140 | *(u32 *) table_desc->pointer->signature)); | ||
| 141 | } | ||
| 142 | return_ACPI_STATUS(AE_BAD_SIGNATURE); | ||
| 143 | } | ||
| 144 | 133 | ||
| 145 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 134 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
| 146 | 135 | ||
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index fb57b93c2495..0e319604d3e7 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c | |||
| @@ -540,7 +540,7 @@ static acpi_status acpi_tb_load_namespace(void) | |||
| 540 | acpi_tb_print_table_header(0, table); | 540 | acpi_tb_print_table_header(0, table); |
| 541 | 541 | ||
| 542 | if (no_auto_ssdt == 0) { | 542 | if (no_auto_ssdt == 0) { |
| 543 | printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\""); | 543 | printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); |
| 544 | } | 544 | } |
| 545 | } | 545 | } |
| 546 | 546 | ||
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 504385b1f211..84c795fb9b1e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
| @@ -364,10 +364,17 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) | |||
| 364 | if (flag & ACPI_TRIPS_CRITICAL) { | 364 | if (flag & ACPI_TRIPS_CRITICAL) { |
| 365 | status = acpi_evaluate_integer(tz->device->handle, | 365 | status = acpi_evaluate_integer(tz->device->handle, |
| 366 | "_CRT", NULL, &tz->trips.critical.temperature); | 366 | "_CRT", NULL, &tz->trips.critical.temperature); |
| 367 | if (ACPI_FAILURE(status)) { | 367 | /* |
| 368 | * Treat freezing temperatures as invalid as well; some | ||
| 369 | * BIOSes return really low values and cause reboots at startup. | ||
| 370 | * Below zero (Celcius) values clearly aren't right for sure.. | ||
| 371 | * ... so lets discard those as invalid. | ||
| 372 | */ | ||
| 373 | if (ACPI_FAILURE(status) || | ||
| 374 | tz->trips.critical.temperature <= 2732) { | ||
| 368 | tz->trips.critical.flags.valid = 0; | 375 | tz->trips.critical.flags.valid = 0; |
| 369 | ACPI_EXCEPTION((AE_INFO, status, | 376 | ACPI_EXCEPTION((AE_INFO, status, |
| 370 | "No critical threshold")); | 377 | "No or invalid critical threshold")); |
| 371 | return -ENODEV; | 378 | return -ENODEV; |
| 372 | } else { | 379 | } else { |
| 373 | tz->trips.critical.flags.valid = 1; | 380 | tz->trips.critical.flags.valid = 1; |
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index e4ba7192cd15..1f057b71db1a 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c | |||
| @@ -1048,6 +1048,7 @@ acpi_ut_exception(char *module_name, | |||
| 1048 | va_start(args, format); | 1048 | va_start(args, format); |
| 1049 | acpi_os_vprintf(format, args); | 1049 | acpi_os_vprintf(format, args); |
| 1050 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); | 1050 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); |
| 1051 | va_end(args); | ||
| 1051 | } | 1052 | } |
| 1052 | 1053 | ||
| 1053 | EXPORT_SYMBOL(acpi_ut_exception); | 1054 | EXPORT_SYMBOL(acpi_ut_exception); |
| @@ -1063,7 +1064,6 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) | |||
| 1063 | acpi_os_vprintf(format, args); | 1064 | acpi_os_vprintf(format, args); |
| 1064 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); | 1065 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); |
| 1065 | va_end(args); | 1066 | va_end(args); |
| 1066 | va_end(args); | ||
| 1067 | } | 1067 | } |
| 1068 | 1068 | ||
| 1069 | void ACPI_INTERNAL_VAR_XFACE | 1069 | void ACPI_INTERNAL_VAR_XFACE |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fc555a90bb21..23554b676d6e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
| @@ -38,6 +38,8 @@ static void cpuidle_kick_cpus(void) | |||
| 38 | static void cpuidle_kick_cpus(void) {} | 38 | static void cpuidle_kick_cpus(void) {} |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | static int __cpuidle_register_device(struct cpuidle_device *dev); | ||
| 42 | |||
| 41 | /** | 43 | /** |
| 42 | * cpuidle_idle_call - the main idle loop | 44 | * cpuidle_idle_call - the main idle loop |
| 43 | * | 45 | * |
| @@ -138,6 +140,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev) | |||
| 138 | if (!dev->state_count) | 140 | if (!dev->state_count) |
| 139 | return -EINVAL; | 141 | return -EINVAL; |
| 140 | 142 | ||
| 143 | if (dev->registered == 0) { | ||
| 144 | ret = __cpuidle_register_device(dev); | ||
| 145 | if (ret) | ||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | |||
| 141 | if ((ret = cpuidle_add_state_sysfs(dev))) | 149 | if ((ret = cpuidle_add_state_sysfs(dev))) |
| 142 | return ret; | 150 | return ret; |
| 143 | 151 | ||
| @@ -232,10 +240,13 @@ static void poll_idle_init(struct cpuidle_device *dev) {} | |||
| 232 | #endif /* CONFIG_ARCH_HAS_CPU_RELAX */ | 240 | #endif /* CONFIG_ARCH_HAS_CPU_RELAX */ |
| 233 | 241 | ||
| 234 | /** | 242 | /** |
| 235 | * cpuidle_register_device - registers a CPU's idle PM feature | 243 | * __cpuidle_register_device - internal register function called before register |
| 244 | * and enable routines | ||
| 236 | * @dev: the cpu | 245 | * @dev: the cpu |
| 246 | * | ||
| 247 | * cpuidle_lock mutex must be held before this is called | ||
| 237 | */ | 248 | */ |
| 238 | int cpuidle_register_device(struct cpuidle_device *dev) | 249 | static int __cpuidle_register_device(struct cpuidle_device *dev) |
| 239 | { | 250 | { |
| 240 | int ret; | 251 | int ret; |
| 241 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); | 252 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); |
| @@ -247,18 +258,34 @@ int cpuidle_register_device(struct cpuidle_device *dev) | |||
| 247 | 258 | ||
| 248 | init_completion(&dev->kobj_unregister); | 259 | init_completion(&dev->kobj_unregister); |
| 249 | 260 | ||
| 250 | mutex_lock(&cpuidle_lock); | ||
| 251 | |||
| 252 | poll_idle_init(dev); | 261 | poll_idle_init(dev); |
| 253 | 262 | ||
| 254 | per_cpu(cpuidle_devices, dev->cpu) = dev; | 263 | per_cpu(cpuidle_devices, dev->cpu) = dev; |
| 255 | list_add(&dev->device_list, &cpuidle_detected_devices); | 264 | list_add(&dev->device_list, &cpuidle_detected_devices); |
| 256 | if ((ret = cpuidle_add_sysfs(sys_dev))) { | 265 | if ((ret = cpuidle_add_sysfs(sys_dev))) { |
| 257 | mutex_unlock(&cpuidle_lock); | ||
| 258 | module_put(cpuidle_curr_driver->owner); | 266 | module_put(cpuidle_curr_driver->owner); |
| 259 | return ret; | 267 | return ret; |
| 260 | } | 268 | } |
| 261 | 269 | ||
| 270 | dev->registered = 1; | ||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | /** | ||
| 275 | * cpuidle_register_device - registers a CPU's idle PM feature | ||
| 276 | * @dev: the cpu | ||
| 277 | */ | ||
| 278 | int cpuidle_register_device(struct cpuidle_device *dev) | ||
| 279 | { | ||
| 280 | int ret; | ||
| 281 | |||
| 282 | mutex_lock(&cpuidle_lock); | ||
| 283 | |||
| 284 | if ((ret = __cpuidle_register_device(dev))) { | ||
| 285 | mutex_unlock(&cpuidle_lock); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | |||
| 262 | cpuidle_enable_device(dev); | 289 | cpuidle_enable_device(dev); |
| 263 | cpuidle_install_idle_handler(); | 290 | cpuidle_install_idle_handler(); |
| 264 | 291 | ||
| @@ -278,6 +305,9 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) | |||
| 278 | { | 305 | { |
| 279 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); | 306 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); |
| 280 | 307 | ||
| 308 | if (dev->registered == 0) | ||
| 309 | return; | ||
| 310 | |||
| 281 | cpuidle_pause_and_lock(); | 311 | cpuidle_pause_and_lock(); |
| 282 | 312 | ||
| 283 | cpuidle_disable_device(dev); | 313 | cpuidle_disable_device(dev); |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index a0ce0b2fa03e..b5969298f3d3 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -1293,7 +1293,7 @@ static void tpacpi_input_send_radiosw(void) | |||
| 1293 | mutex_lock(&tpacpi_inputdev_send_mutex); | 1293 | mutex_lock(&tpacpi_inputdev_send_mutex); |
| 1294 | 1294 | ||
| 1295 | input_report_switch(tpacpi_inputdev, | 1295 | input_report_switch(tpacpi_inputdev, |
| 1296 | SW_RADIO, !!wlsw); | 1296 | SW_RFKILL_ALL, !!wlsw); |
| 1297 | input_sync(tpacpi_inputdev); | 1297 | input_sync(tpacpi_inputdev); |
| 1298 | 1298 | ||
| 1299 | mutex_unlock(&tpacpi_inputdev_send_mutex); | 1299 | mutex_unlock(&tpacpi_inputdev_send_mutex); |
| @@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = { | |||
| 1921 | &dev_attr_hotkey_wakeup_hotunplug_complete.attr, | 1921 | &dev_attr_hotkey_wakeup_hotunplug_complete.attr, |
| 1922 | }; | 1922 | }; |
| 1923 | 1923 | ||
| 1924 | static void hotkey_exit(void) | ||
| 1925 | { | ||
| 1926 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | ||
| 1927 | hotkey_poll_stop_sync(); | ||
| 1928 | #endif | ||
| 1929 | |||
| 1930 | if (hotkey_dev_attributes) | ||
| 1931 | delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); | ||
| 1932 | |||
| 1933 | kfree(hotkey_keycode_map); | ||
| 1934 | |||
| 1935 | if (tp_features.hotkey) { | ||
| 1936 | dbg_printk(TPACPI_DBG_EXIT, | ||
| 1937 | "restoring original hot key mask\n"); | ||
| 1938 | /* no short-circuit boolean operator below! */ | ||
| 1939 | if ((hotkey_mask_set(hotkey_orig_mask) | | ||
| 1940 | hotkey_status_set(hotkey_orig_status)) != 0) | ||
| 1941 | printk(TPACPI_ERR | ||
| 1942 | "failed to restore hot key mask " | ||
| 1943 | "to BIOS defaults\n"); | ||
| 1944 | } | ||
| 1945 | } | ||
| 1946 | |||
| 1924 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 1947 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
| 1925 | { | 1948 | { |
| 1926 | /* Requirements for changing the default keymaps: | 1949 | /* Requirements for changing the default keymaps: |
| @@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 2060 | vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", | 2083 | vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", |
| 2061 | str_supported(tp_features.hotkey)); | 2084 | str_supported(tp_features.hotkey)); |
| 2062 | 2085 | ||
| 2063 | if (tp_features.hotkey) { | 2086 | if (!tp_features.hotkey) |
| 2064 | hotkey_dev_attributes = create_attr_set(13, NULL); | 2087 | return 1; |
| 2065 | if (!hotkey_dev_attributes) | ||
| 2066 | return -ENOMEM; | ||
| 2067 | res = add_many_to_attr_set(hotkey_dev_attributes, | ||
| 2068 | hotkey_attributes, | ||
| 2069 | ARRAY_SIZE(hotkey_attributes)); | ||
| 2070 | if (res) | ||
| 2071 | return res; | ||
| 2072 | 2088 | ||
| 2073 | /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, | 2089 | hotkey_dev_attributes = create_attr_set(13, NULL); |
| 2074 | A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking | 2090 | if (!hotkey_dev_attributes) |
| 2075 | for HKEY interface version 0x100 */ | 2091 | return -ENOMEM; |
| 2076 | if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { | 2092 | res = add_many_to_attr_set(hotkey_dev_attributes, |
| 2077 | if ((hkeyv >> 8) != 1) { | 2093 | hotkey_attributes, |
| 2078 | printk(TPACPI_ERR "unknown version of the " | 2094 | ARRAY_SIZE(hotkey_attributes)); |
| 2079 | "HKEY interface: 0x%x\n", hkeyv); | 2095 | if (res) |
| 2080 | printk(TPACPI_ERR "please report this to %s\n", | 2096 | goto err_exit; |
| 2081 | TPACPI_MAIL); | 2097 | |
| 2082 | } else { | 2098 | /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, |
| 2083 | /* | 2099 | A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking |
| 2084 | * MHKV 0x100 in A31, R40, R40e, | 2100 | for HKEY interface version 0x100 */ |
| 2085 | * T4x, X31, and later | 2101 | if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { |
| 2086 | */ | 2102 | if ((hkeyv >> 8) != 1) { |
| 2087 | tp_features.hotkey_mask = 1; | 2103 | printk(TPACPI_ERR "unknown version of the " |
| 2088 | } | 2104 | "HKEY interface: 0x%x\n", hkeyv); |
| 2105 | printk(TPACPI_ERR "please report this to %s\n", | ||
| 2106 | TPACPI_MAIL); | ||
| 2107 | } else { | ||
| 2108 | /* | ||
| 2109 | * MHKV 0x100 in A31, R40, R40e, | ||
| 2110 | * T4x, X31, and later | ||
| 2111 | */ | ||
| 2112 | tp_features.hotkey_mask = 1; | ||
| 2089 | } | 2113 | } |
| 2114 | } | ||
| 2090 | 2115 | ||
| 2091 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", | 2116 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", |
| 2092 | str_supported(tp_features.hotkey_mask)); | 2117 | str_supported(tp_features.hotkey_mask)); |
| 2093 | 2118 | ||
| 2094 | if (tp_features.hotkey_mask) { | 2119 | if (tp_features.hotkey_mask) { |
| 2095 | if (!acpi_evalf(hkey_handle, &hotkey_all_mask, | 2120 | if (!acpi_evalf(hkey_handle, &hotkey_all_mask, |
| 2096 | "MHKA", "qd")) { | 2121 | "MHKA", "qd")) { |
| 2097 | printk(TPACPI_ERR | 2122 | printk(TPACPI_ERR |
| 2098 | "missing MHKA handler, " | 2123 | "missing MHKA handler, " |
| 2099 | "please report this to %s\n", | 2124 | "please report this to %s\n", |
| 2100 | TPACPI_MAIL); | 2125 | TPACPI_MAIL); |
| 2101 | /* FN+F12, FN+F4, FN+F3 */ | 2126 | /* FN+F12, FN+F4, FN+F3 */ |
| 2102 | hotkey_all_mask = 0x080cU; | 2127 | hotkey_all_mask = 0x080cU; |
| 2103 | } | ||
| 2104 | } | 2128 | } |
| 2129 | } | ||
| 2105 | 2130 | ||
| 2106 | /* hotkey_source_mask *must* be zero for | 2131 | /* hotkey_source_mask *must* be zero for |
| 2107 | * the first hotkey_mask_get */ | 2132 | * the first hotkey_mask_get */ |
| 2108 | res = hotkey_status_get(&hotkey_orig_status); | 2133 | res = hotkey_status_get(&hotkey_orig_status); |
| 2109 | if (!res && tp_features.hotkey_mask) { | 2134 | if (res) |
| 2110 | res = hotkey_mask_get(); | 2135 | goto err_exit; |
| 2111 | hotkey_orig_mask = hotkey_mask; | 2136 | |
| 2112 | if (!res) { | 2137 | if (tp_features.hotkey_mask) { |
| 2113 | res = add_many_to_attr_set( | 2138 | res = hotkey_mask_get(); |
| 2114 | hotkey_dev_attributes, | 2139 | if (res) |
| 2115 | hotkey_mask_attributes, | 2140 | goto err_exit; |
| 2116 | ARRAY_SIZE(hotkey_mask_attributes)); | 2141 | |
| 2117 | } | 2142 | hotkey_orig_mask = hotkey_mask; |
| 2118 | } | 2143 | res = add_many_to_attr_set( |
| 2144 | hotkey_dev_attributes, | ||
| 2145 | hotkey_mask_attributes, | ||
| 2146 | ARRAY_SIZE(hotkey_mask_attributes)); | ||
| 2147 | if (res) | ||
| 2148 | goto err_exit; | ||
| 2149 | } | ||
| 2119 | 2150 | ||
| 2120 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | 2151 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL |
| 2121 | if (tp_features.hotkey_mask) { | 2152 | if (tp_features.hotkey_mask) { |
| 2122 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK | 2153 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK |
| 2123 | & ~hotkey_all_mask; | 2154 | & ~hotkey_all_mask; |
| 2124 | } else { | 2155 | } else { |
| 2125 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; | 2156 | hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; |
| 2126 | } | 2157 | } |
| 2127 | 2158 | ||
| 2128 | vdbg_printk(TPACPI_DBG_INIT, | 2159 | vdbg_printk(TPACPI_DBG_INIT, |
| 2129 | "hotkey source mask 0x%08x, polling freq %d\n", | 2160 | "hotkey source mask 0x%08x, polling freq %d\n", |
| 2130 | hotkey_source_mask, hotkey_poll_freq); | 2161 | hotkey_source_mask, hotkey_poll_freq); |
| 2131 | #endif | 2162 | #endif |
| 2132 | 2163 | ||
| 2133 | /* Not all thinkpads have a hardware radio switch */ | 2164 | /* Not all thinkpads have a hardware radio switch */ |
| 2134 | if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { | 2165 | if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { |
| 2135 | tp_features.hotkey_wlsw = 1; | 2166 | tp_features.hotkey_wlsw = 1; |
| 2136 | printk(TPACPI_INFO | 2167 | printk(TPACPI_INFO |
| 2137 | "radio switch found; radios are %s\n", | 2168 | "radio switch found; radios are %s\n", |
| 2138 | enabled(status, 0)); | 2169 | enabled(status, 0)); |
| 2139 | res = add_to_attr_set(hotkey_dev_attributes, | 2170 | res = add_to_attr_set(hotkey_dev_attributes, |
| 2140 | &dev_attr_hotkey_radio_sw.attr); | 2171 | &dev_attr_hotkey_radio_sw.attr); |
| 2141 | } | 2172 | } |
| 2142 | 2173 | ||
| 2143 | /* For X41t, X60t, X61t Tablets... */ | 2174 | /* For X41t, X60t, X61t Tablets... */ |
| 2144 | if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { | 2175 | if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { |
| 2145 | tp_features.hotkey_tablet = 1; | 2176 | tp_features.hotkey_tablet = 1; |
| 2146 | printk(TPACPI_INFO | 2177 | printk(TPACPI_INFO |
| 2147 | "possible tablet mode switch found; " | 2178 | "possible tablet mode switch found; " |
| 2148 | "ThinkPad in %s mode\n", | 2179 | "ThinkPad in %s mode\n", |
| 2149 | (status & TP_HOTKEY_TABLET_MASK)? | 2180 | (status & TP_HOTKEY_TABLET_MASK)? |
| 2150 | "tablet" : "laptop"); | 2181 | "tablet" : "laptop"); |
| 2151 | res = add_to_attr_set(hotkey_dev_attributes, | 2182 | res = add_to_attr_set(hotkey_dev_attributes, |
| 2152 | &dev_attr_hotkey_tablet_mode.attr); | 2183 | &dev_attr_hotkey_tablet_mode.attr); |
| 2153 | } | 2184 | } |
| 2154 | 2185 | ||
| 2155 | if (!res) | 2186 | if (!res) |
| 2156 | res = register_attr_set_with_sysfs( | 2187 | res = register_attr_set_with_sysfs( |
| 2157 | hotkey_dev_attributes, | 2188 | hotkey_dev_attributes, |
| 2158 | &tpacpi_pdev->dev.kobj); | 2189 | &tpacpi_pdev->dev.kobj); |
| 2159 | if (res) | 2190 | if (res) |
| 2160 | return res; | 2191 | goto err_exit; |
| 2161 | 2192 | ||
| 2162 | /* Set up key map */ | 2193 | /* Set up key map */ |
| 2163 | 2194 | ||
| 2164 | hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, | 2195 | hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, |
| 2165 | GFP_KERNEL); | 2196 | GFP_KERNEL); |
| 2166 | if (!hotkey_keycode_map) { | 2197 | if (!hotkey_keycode_map) { |
| 2167 | printk(TPACPI_ERR | 2198 | printk(TPACPI_ERR |
| 2168 | "failed to allocate memory for key map\n"); | 2199 | "failed to allocate memory for key map\n"); |
| 2169 | return -ENOMEM; | 2200 | res = -ENOMEM; |
| 2170 | } | 2201 | goto err_exit; |
| 2202 | } | ||
| 2171 | 2203 | ||
| 2172 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | 2204 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { |
| 2173 | dbg_printk(TPACPI_DBG_INIT, | 2205 | dbg_printk(TPACPI_DBG_INIT, |
| 2174 | "using Lenovo default hot key map\n"); | 2206 | "using Lenovo default hot key map\n"); |
| 2175 | memcpy(hotkey_keycode_map, &lenovo_keycode_map, | 2207 | memcpy(hotkey_keycode_map, &lenovo_keycode_map, |
| 2176 | TPACPI_HOTKEY_MAP_SIZE); | 2208 | TPACPI_HOTKEY_MAP_SIZE); |
| 2209 | } else { | ||
| 2210 | dbg_printk(TPACPI_DBG_INIT, | ||
| 2211 | "using IBM default hot key map\n"); | ||
| 2212 | memcpy(hotkey_keycode_map, &ibm_keycode_map, | ||
| 2213 | TPACPI_HOTKEY_MAP_SIZE); | ||
| 2214 | } | ||
| 2215 | |||
| 2216 | set_bit(EV_KEY, tpacpi_inputdev->evbit); | ||
| 2217 | set_bit(EV_MSC, tpacpi_inputdev->evbit); | ||
| 2218 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); | ||
| 2219 | tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; | ||
| 2220 | tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; | ||
| 2221 | tpacpi_inputdev->keycode = hotkey_keycode_map; | ||
| 2222 | for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { | ||
| 2223 | if (hotkey_keycode_map[i] != KEY_RESERVED) { | ||
| 2224 | set_bit(hotkey_keycode_map[i], | ||
| 2225 | tpacpi_inputdev->keybit); | ||
| 2177 | } else { | 2226 | } else { |
| 2178 | dbg_printk(TPACPI_DBG_INIT, | 2227 | if (i < sizeof(hotkey_reserved_mask)*8) |
| 2179 | "using IBM default hot key map\n"); | 2228 | hotkey_reserved_mask |= 1 << i; |
| 2180 | memcpy(hotkey_keycode_map, &ibm_keycode_map, | ||
| 2181 | TPACPI_HOTKEY_MAP_SIZE); | ||
| 2182 | } | ||
| 2183 | |||
| 2184 | set_bit(EV_KEY, tpacpi_inputdev->evbit); | ||
| 2185 | set_bit(EV_MSC, tpacpi_inputdev->evbit); | ||
| 2186 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); | ||
| 2187 | tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; | ||
| 2188 | tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; | ||
| 2189 | tpacpi_inputdev->keycode = hotkey_keycode_map; | ||
| 2190 | for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { | ||
| 2191 | if (hotkey_keycode_map[i] != KEY_RESERVED) { | ||
| 2192 | set_bit(hotkey_keycode_map[i], | ||
| 2193 | tpacpi_inputdev->keybit); | ||
| 2194 | } else { | ||
| 2195 | if (i < sizeof(hotkey_reserved_mask)*8) | ||
| 2196 | hotkey_reserved_mask |= 1 << i; | ||
| 2197 | } | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | if (tp_features.hotkey_wlsw) { | ||
| 2201 | set_bit(EV_SW, tpacpi_inputdev->evbit); | ||
| 2202 | set_bit(SW_RADIO, tpacpi_inputdev->swbit); | ||
| 2203 | } | ||
| 2204 | if (tp_features.hotkey_tablet) { | ||
| 2205 | set_bit(EV_SW, tpacpi_inputdev->evbit); | ||
| 2206 | set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); | ||
| 2207 | } | 2229 | } |
| 2230 | } | ||
| 2208 | 2231 | ||
| 2209 | /* Do not issue duplicate brightness change events to | 2232 | if (tp_features.hotkey_wlsw) { |
| 2210 | * userspace */ | 2233 | set_bit(EV_SW, tpacpi_inputdev->evbit); |
| 2211 | if (!tp_features.bright_acpimode) | 2234 | set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); |
| 2212 | /* update bright_acpimode... */ | 2235 | } |
| 2213 | tpacpi_check_std_acpi_brightness_support(); | 2236 | if (tp_features.hotkey_tablet) { |
| 2214 | 2237 | set_bit(EV_SW, tpacpi_inputdev->evbit); | |
| 2215 | if (tp_features.bright_acpimode) { | 2238 | set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); |
| 2216 | printk(TPACPI_INFO | 2239 | } |
| 2217 | "This ThinkPad has standard ACPI backlight " | ||
| 2218 | "brightness control, supported by the ACPI " | ||
| 2219 | "video driver\n"); | ||
| 2220 | printk(TPACPI_NOTICE | ||
| 2221 | "Disabling thinkpad-acpi brightness events " | ||
| 2222 | "by default...\n"); | ||
| 2223 | |||
| 2224 | /* The hotkey_reserved_mask change below is not | ||
| 2225 | * necessary while the keys are at KEY_RESERVED in the | ||
| 2226 | * default map, but better safe than sorry, leave it | ||
| 2227 | * here as a marker of what we have to do, especially | ||
| 2228 | * when we finally become able to set this at runtime | ||
| 2229 | * on response to X.org requests */ | ||
| 2230 | hotkey_reserved_mask |= | ||
| 2231 | (1 << TP_ACPI_HOTKEYSCAN_FNHOME) | ||
| 2232 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); | ||
| 2233 | } | ||
| 2234 | 2240 | ||
| 2235 | dbg_printk(TPACPI_DBG_INIT, | 2241 | /* Do not issue duplicate brightness change events to |
| 2236 | "enabling hot key handling\n"); | 2242 | * userspace */ |
| 2237 | res = hotkey_status_set(1); | 2243 | if (!tp_features.bright_acpimode) |
| 2238 | if (res) | 2244 | /* update bright_acpimode... */ |
| 2239 | return res; | 2245 | tpacpi_check_std_acpi_brightness_support(); |
| 2240 | res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) | ||
| 2241 | & ~hotkey_reserved_mask) | ||
| 2242 | | hotkey_orig_mask); | ||
| 2243 | if (res < 0 && res != -ENXIO) | ||
| 2244 | return res; | ||
| 2245 | 2246 | ||
| 2246 | dbg_printk(TPACPI_DBG_INIT, | 2247 | if (tp_features.bright_acpimode) { |
| 2247 | "legacy hot key reporting over procfs %s\n", | 2248 | printk(TPACPI_INFO |
| 2248 | (hotkey_report_mode < 2) ? | 2249 | "This ThinkPad has standard ACPI backlight " |
| 2249 | "enabled" : "disabled"); | 2250 | "brightness control, supported by the ACPI " |
| 2251 | "video driver\n"); | ||
| 2252 | printk(TPACPI_NOTICE | ||
| 2253 | "Disabling thinkpad-acpi brightness events " | ||
| 2254 | "by default...\n"); | ||
| 2255 | |||
| 2256 | /* The hotkey_reserved_mask change below is not | ||
| 2257 | * necessary while the keys are at KEY_RESERVED in the | ||
| 2258 | * default map, but better safe than sorry, leave it | ||
| 2259 | * here as a marker of what we have to do, especially | ||
| 2260 | * when we finally become able to set this at runtime | ||
| 2261 | * on response to X.org requests */ | ||
| 2262 | hotkey_reserved_mask |= | ||
| 2263 | (1 << TP_ACPI_HOTKEYSCAN_FNHOME) | ||
| 2264 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); | ||
| 2265 | } | ||
| 2266 | |||
| 2267 | dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); | ||
| 2268 | res = hotkey_status_set(1); | ||
| 2269 | if (res) { | ||
| 2270 | hotkey_exit(); | ||
| 2271 | return res; | ||
| 2272 | } | ||
| 2273 | res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) | ||
| 2274 | & ~hotkey_reserved_mask) | ||
| 2275 | | hotkey_orig_mask); | ||
| 2276 | if (res < 0 && res != -ENXIO) { | ||
| 2277 | hotkey_exit(); | ||
| 2278 | return res; | ||
| 2279 | } | ||
| 2250 | 2280 | ||
| 2251 | tpacpi_inputdev->open = &hotkey_inputdev_open; | 2281 | dbg_printk(TPACPI_DBG_INIT, |
| 2252 | tpacpi_inputdev->close = &hotkey_inputdev_close; | 2282 | "legacy hot key reporting over procfs %s\n", |
| 2283 | (hotkey_report_mode < 2) ? | ||
| 2284 | "enabled" : "disabled"); | ||
| 2253 | 2285 | ||
| 2254 | hotkey_poll_setup_safe(1); | 2286 | tpacpi_inputdev->open = &hotkey_inputdev_open; |
| 2255 | tpacpi_input_send_radiosw(); | 2287 | tpacpi_inputdev->close = &hotkey_inputdev_close; |
| 2256 | tpacpi_input_send_tabletsw(); | ||
| 2257 | } | ||
| 2258 | 2288 | ||
| 2259 | return (tp_features.hotkey)? 0 : 1; | 2289 | hotkey_poll_setup_safe(1); |
| 2260 | } | 2290 | tpacpi_input_send_radiosw(); |
| 2291 | tpacpi_input_send_tabletsw(); | ||
| 2261 | 2292 | ||
| 2262 | static void hotkey_exit(void) | 2293 | return 0; |
| 2263 | { | ||
| 2264 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL | ||
| 2265 | hotkey_poll_stop_sync(); | ||
| 2266 | #endif | ||
| 2267 | 2294 | ||
| 2268 | if (tp_features.hotkey) { | 2295 | err_exit: |
| 2269 | dbg_printk(TPACPI_DBG_EXIT, | 2296 | delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); |
| 2270 | "restoring original hot key mask\n"); | 2297 | hotkey_dev_attributes = NULL; |
| 2271 | /* no short-circuit boolean operator below! */ | ||
| 2272 | if ((hotkey_mask_set(hotkey_orig_mask) | | ||
| 2273 | hotkey_status_set(hotkey_orig_status)) != 0) | ||
| 2274 | printk(TPACPI_ERR | ||
| 2275 | "failed to restore hot key mask " | ||
| 2276 | "to BIOS defaults\n"); | ||
| 2277 | } | ||
| 2278 | 2298 | ||
| 2279 | if (hotkey_dev_attributes) { | 2299 | return (res < 0)? res : 1; |
| 2280 | delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); | ||
| 2281 | hotkey_dev_attributes = NULL; | ||
| 2282 | } | ||
| 2283 | } | 2300 | } |
| 2284 | 2301 | ||
| 2285 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 2302 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
| @@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = { | |||
| 3319 | 3336 | ||
| 3320 | static int __init light_init(struct ibm_init_struct *iibm) | 3337 | static int __init light_init(struct ibm_init_struct *iibm) |
| 3321 | { | 3338 | { |
| 3322 | int rc = 0; | 3339 | int rc; |
| 3323 | 3340 | ||
| 3324 | vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); | 3341 | vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); |
| 3325 | 3342 | ||
| @@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm) | |||
| 3337 | tp_features.light_status = | 3354 | tp_features.light_status = |
| 3338 | acpi_evalf(ec_handle, NULL, "KBLT", "qv"); | 3355 | acpi_evalf(ec_handle, NULL, "KBLT", "qv"); |
| 3339 | 3356 | ||
| 3340 | vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", | 3357 | vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n", |
| 3341 | str_supported(tp_features.light)); | 3358 | str_supported(tp_features.light), |
| 3359 | str_supported(tp_features.light_status)); | ||
| 3342 | 3360 | ||
| 3343 | if (tp_features.light) { | 3361 | if (!tp_features.light) |
| 3344 | rc = led_classdev_register(&tpacpi_pdev->dev, | 3362 | return 1; |
| 3345 | &tpacpi_led_thinklight.led_classdev); | 3363 | |
| 3346 | } | 3364 | rc = led_classdev_register(&tpacpi_pdev->dev, |
| 3365 | &tpacpi_led_thinklight.led_classdev); | ||
| 3347 | 3366 | ||
| 3348 | if (rc < 0) { | 3367 | if (rc < 0) { |
| 3349 | tp_features.light = 0; | 3368 | tp_features.light = 0; |
| 3350 | tp_features.light_status = 0; | 3369 | tp_features.light_status = 0; |
| 3351 | } else { | 3370 | } else { |
| 3352 | rc = (tp_features.light)? 0 : 1; | 3371 | rc = 0; |
| 3353 | } | 3372 | } |
| 3373 | |||
| 3354 | return rc; | 3374 | return rc; |
| 3355 | } | 3375 | } |
| 3356 | 3376 | ||
| @@ -3833,7 +3853,7 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | |||
| 3833 | "tpacpi::standby", | 3853 | "tpacpi::standby", |
| 3834 | }; | 3854 | }; |
| 3835 | 3855 | ||
| 3836 | static int led_get_status(unsigned int led) | 3856 | static int led_get_status(const unsigned int led) |
| 3837 | { | 3857 | { |
| 3838 | int status; | 3858 | int status; |
| 3839 | enum led_status_t led_s; | 3859 | enum led_status_t led_s; |
| @@ -3857,41 +3877,42 @@ static int led_get_status(unsigned int led) | |||
| 3857 | /* not reached */ | 3877 | /* not reached */ |
| 3858 | } | 3878 | } |
| 3859 | 3879 | ||
| 3860 | static int led_set_status(unsigned int led, enum led_status_t ledstatus) | 3880 | static int led_set_status(const unsigned int led, |
| 3881 | const enum led_status_t ledstatus) | ||
| 3861 | { | 3882 | { |
| 3862 | /* off, on, blink. Index is led_status_t */ | 3883 | /* off, on, blink. Index is led_status_t */ |
| 3863 | static const int led_sled_arg1[] = { 0, 1, 3 }; | 3884 | static const unsigned int led_sled_arg1[] = { 0, 1, 3 }; |
| 3864 | static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ | 3885 | static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 }; |
| 3865 | static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ | ||
| 3866 | static const int led_led_arg1[] = { 0, 0x80, 0xc0 }; | ||
| 3867 | 3886 | ||
| 3868 | int rc = 0; | 3887 | int rc = 0; |
| 3869 | 3888 | ||
| 3870 | switch (led_supported) { | 3889 | switch (led_supported) { |
| 3871 | case TPACPI_LED_570: | 3890 | case TPACPI_LED_570: |
| 3872 | /* 570 */ | 3891 | /* 570 */ |
| 3873 | led = 1 << led; | 3892 | if (led > 7) |
| 3874 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | 3893 | return -EINVAL; |
| 3875 | led, led_sled_arg1[ledstatus])) | 3894 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", |
| 3876 | rc = -EIO; | 3895 | (1 << led), led_sled_arg1[ledstatus])) |
| 3877 | break; | 3896 | rc = -EIO; |
| 3897 | break; | ||
| 3878 | case TPACPI_LED_OLD: | 3898 | case TPACPI_LED_OLD: |
| 3879 | /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ | 3899 | /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ |
| 3880 | led = 1 << led; | 3900 | if (led > 7) |
| 3881 | rc = ec_write(TPACPI_LED_EC_HLMS, led); | 3901 | return -EINVAL; |
| 3882 | if (rc >= 0) | 3902 | rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); |
| 3883 | rc = ec_write(TPACPI_LED_EC_HLBL, | 3903 | if (rc >= 0) |
| 3884 | led * led_exp_hlbl[ledstatus]); | 3904 | rc = ec_write(TPACPI_LED_EC_HLBL, |
| 3885 | if (rc >= 0) | 3905 | (ledstatus == TPACPI_LED_BLINK) << led); |
| 3886 | rc = ec_write(TPACPI_LED_EC_HLCL, | 3906 | if (rc >= 0) |
| 3887 | led * led_exp_hlcl[ledstatus]); | 3907 | rc = ec_write(TPACPI_LED_EC_HLCL, |
| 3888 | break; | 3908 | (ledstatus != TPACPI_LED_OFF) << led); |
| 3909 | break; | ||
| 3889 | case TPACPI_LED_NEW: | 3910 | case TPACPI_LED_NEW: |
| 3890 | /* all others */ | 3911 | /* all others */ |
| 3891 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | 3912 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", |
| 3892 | led, led_led_arg1[ledstatus])) | 3913 | led, led_led_arg1[ledstatus])) |
| 3893 | rc = -EIO; | 3914 | rc = -EIO; |
| 3894 | break; | 3915 | break; |
| 3895 | default: | 3916 | default: |
| 3896 | rc = -ENXIO; | 3917 | rc = -ENXIO; |
| 3897 | } | 3918 | } |
| @@ -3978,7 +3999,6 @@ static void led_exit(void) | |||
| 3978 | } | 3999 | } |
| 3979 | 4000 | ||
| 3980 | kfree(tpacpi_leds); | 4001 | kfree(tpacpi_leds); |
| 3981 | tpacpi_leds = NULL; | ||
| 3982 | } | 4002 | } |
| 3983 | 4003 | ||
| 3984 | static int __init led_init(struct ibm_init_struct *iibm) | 4004 | static int __init led_init(struct ibm_init_struct *iibm) |
| @@ -4802,7 +4822,6 @@ static void brightness_exit(void) | |||
| 4802 | vdbg_printk(TPACPI_DBG_EXIT, | 4822 | vdbg_printk(TPACPI_DBG_EXIT, |
| 4803 | "calling backlight_device_unregister()\n"); | 4823 | "calling backlight_device_unregister()\n"); |
| 4804 | backlight_device_unregister(ibm_backlight_device); | 4824 | backlight_device_unregister(ibm_backlight_device); |
| 4805 | ibm_backlight_device = NULL; | ||
| 4806 | } | 4825 | } |
| 4807 | } | 4826 | } |
| 4808 | 4827 | ||
| @@ -5764,11 +5783,16 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 5764 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { | 5783 | fan_control_access_mode != TPACPI_FAN_WR_NONE) { |
| 5765 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, | 5784 | rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, |
| 5766 | &fan_attr_group); | 5785 | &fan_attr_group); |
| 5767 | if (!(rc < 0)) | ||
| 5768 | rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, | ||
| 5769 | &driver_attr_fan_watchdog); | ||
| 5770 | if (rc < 0) | 5786 | if (rc < 0) |
| 5771 | return rc; | 5787 | return rc; |
| 5788 | |||
| 5789 | rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, | ||
| 5790 | &driver_attr_fan_watchdog); | ||
| 5791 | if (rc < 0) { | ||
| 5792 | sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, | ||
| 5793 | &fan_attr_group); | ||
| 5794 | return rc; | ||
| 5795 | } | ||
| 5772 | return 0; | 5796 | return 0; |
| 5773 | } else | 5797 | } else |
| 5774 | return 1; | 5798 | return 1; |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 0201c8adfda7..46c791adb894 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
| @@ -50,15 +50,17 @@ static int irq_flags(int triggering, int polarity, int shareable) | |||
| 50 | flags = IORESOURCE_IRQ_HIGHEDGE; | 50 | flags = IORESOURCE_IRQ_HIGHEDGE; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | if (shareable) | 53 | if (shareable == ACPI_SHARED) |
| 54 | flags |= IORESOURCE_IRQ_SHAREABLE; | 54 | flags |= IORESOURCE_IRQ_SHAREABLE; |
| 55 | 55 | ||
| 56 | return flags; | 56 | return flags; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static void decode_irq_flags(int flag, int *triggering, int *polarity) | 59 | static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, |
| 60 | int *polarity, int *shareable) | ||
| 60 | { | 61 | { |
| 61 | switch (flag) { | 62 | switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL | |
| 63 | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) { | ||
| 62 | case IORESOURCE_IRQ_LOWLEVEL: | 64 | case IORESOURCE_IRQ_LOWLEVEL: |
| 63 | *triggering = ACPI_LEVEL_SENSITIVE; | 65 | *triggering = ACPI_LEVEL_SENSITIVE; |
| 64 | *polarity = ACPI_ACTIVE_LOW; | 66 | *polarity = ACPI_ACTIVE_LOW; |
| @@ -75,7 +77,18 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) | |||
| 75 | *triggering = ACPI_EDGE_SENSITIVE; | 77 | *triggering = ACPI_EDGE_SENSITIVE; |
| 76 | *polarity = ACPI_ACTIVE_HIGH; | 78 | *polarity = ACPI_ACTIVE_HIGH; |
| 77 | break; | 79 | break; |
| 80 | default: | ||
| 81 | dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n", | ||
| 82 | flags); | ||
| 83 | *triggering = ACPI_EDGE_SENSITIVE; | ||
| 84 | *polarity = ACPI_ACTIVE_HIGH; | ||
| 85 | break; | ||
| 78 | } | 86 | } |
| 87 | |||
| 88 | if (flags & IORESOURCE_IRQ_SHAREABLE) | ||
| 89 | *shareable = ACPI_SHARED; | ||
| 90 | else | ||
| 91 | *shareable = ACPI_EXCLUSIVE; | ||
| 79 | } | 92 | } |
| 80 | 93 | ||
| 81 | static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, | 94 | static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, |
| @@ -742,6 +755,9 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) | |||
| 742 | if (pnpacpi_supported_resource(res)) { | 755 | if (pnpacpi_supported_resource(res)) { |
| 743 | (*resource)->type = res->type; | 756 | (*resource)->type = res->type; |
| 744 | (*resource)->length = sizeof(struct acpi_resource); | 757 | (*resource)->length = sizeof(struct acpi_resource); |
| 758 | if (res->type == ACPI_RESOURCE_TYPE_IRQ) | ||
| 759 | (*resource)->data.irq.descriptor_length = | ||
| 760 | res->data.irq.descriptor_length; | ||
| 745 | (*resource)++; | 761 | (*resource)++; |
| 746 | } | 762 | } |
| 747 | 763 | ||
| @@ -788,22 +804,21 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, | |||
| 788 | struct resource *p) | 804 | struct resource *p) |
| 789 | { | 805 | { |
| 790 | struct acpi_resource_irq *irq = &resource->data.irq; | 806 | struct acpi_resource_irq *irq = &resource->data.irq; |
| 791 | int triggering, polarity; | 807 | int triggering, polarity, shareable; |
| 792 | 808 | ||
| 793 | decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); | 809 | decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); |
| 794 | irq->triggering = triggering; | 810 | irq->triggering = triggering; |
| 795 | irq->polarity = polarity; | 811 | irq->polarity = polarity; |
| 796 | if (triggering == ACPI_EDGE_SENSITIVE) | 812 | irq->sharable = shareable; |
| 797 | irq->sharable = ACPI_EXCLUSIVE; | ||
| 798 | else | ||
| 799 | irq->sharable = ACPI_SHARED; | ||
| 800 | irq->interrupt_count = 1; | 813 | irq->interrupt_count = 1; |
| 801 | irq->interrupts[0] = p->start; | 814 | irq->interrupts[0] = p->start; |
| 802 | 815 | ||
| 803 | dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, | 816 | dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n", |
| 817 | (int) p->start, | ||
| 804 | triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", | 818 | triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", |
| 805 | polarity == ACPI_ACTIVE_LOW ? "low" : "high", | 819 | polarity == ACPI_ACTIVE_LOW ? "low" : "high", |
| 806 | irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); | 820 | irq->sharable == ACPI_SHARED ? "shared" : "exclusive", |
| 821 | irq->descriptor_length); | ||
| 807 | } | 822 | } |
| 808 | 823 | ||
| 809 | static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, | 824 | static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, |
| @@ -811,16 +826,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, | |||
| 811 | struct resource *p) | 826 | struct resource *p) |
| 812 | { | 827 | { |
| 813 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; | 828 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; |
| 814 | int triggering, polarity; | 829 | int triggering, polarity, shareable; |
| 815 | 830 | ||
| 816 | decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); | 831 | decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); |
| 817 | extended_irq->producer_consumer = ACPI_CONSUMER; | 832 | extended_irq->producer_consumer = ACPI_CONSUMER; |
| 818 | extended_irq->triggering = triggering; | 833 | extended_irq->triggering = triggering; |
| 819 | extended_irq->polarity = polarity; | 834 | extended_irq->polarity = polarity; |
| 820 | if (triggering == ACPI_EDGE_SENSITIVE) | 835 | extended_irq->sharable = shareable; |
| 821 | extended_irq->sharable = ACPI_EXCLUSIVE; | ||
| 822 | else | ||
| 823 | extended_irq->sharable = ACPI_SHARED; | ||
| 824 | extended_irq->interrupt_count = 1; | 836 | extended_irq->interrupt_count = 1; |
| 825 | extended_irq->interrupts[0] = p->start; | 837 | extended_irq->interrupts[0] = p->start; |
| 826 | 838 | ||
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 06480bcabfdc..06ebb6ef72aa 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
| @@ -319,6 +319,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) | |||
| 319 | #endif /* CONFIG_CPU_FREQ */ | 319 | #endif /* CONFIG_CPU_FREQ */ |
| 320 | 320 | ||
| 321 | /* in processor_throttling.c */ | 321 | /* in processor_throttling.c */ |
| 322 | int acpi_processor_tstate_has_changed(struct acpi_processor *pr); | ||
| 322 | int acpi_processor_get_throttling_info(struct acpi_processor *pr); | 323 | int acpi_processor_get_throttling_info(struct acpi_processor *pr); |
| 323 | extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); | 324 | extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); |
| 324 | extern struct file_operations acpi_processor_throttling_fops; | 325 | extern struct file_operations acpi_processor_throttling_fops; |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 51e6b1e520e6..dcf77fa826b5 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
| @@ -82,6 +82,7 @@ struct cpuidle_state_kobj { | |||
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | struct cpuidle_device { | 84 | struct cpuidle_device { |
| 85 | unsigned int registered:1; | ||
| 85 | unsigned int enabled:1; | 86 | unsigned int enabled:1; |
| 86 | unsigned int cpu; | 87 | unsigned int cpu; |
| 87 | 88 | ||
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index d5d40a9f7929..c6801bffe76d 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
| @@ -53,14 +53,14 @@ struct resource_list { | |||
| 53 | #define IORESOURCE_AUTO 0x40000000 | 53 | #define IORESOURCE_AUTO 0x40000000 |
| 54 | #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ | 54 | #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ |
| 55 | 55 | ||
| 56 | /* ISA PnP IRQ specific bits (IORESOURCE_BITS) */ | 56 | /* PnP IRQ specific bits (IORESOURCE_BITS) */ |
| 57 | #define IORESOURCE_IRQ_HIGHEDGE (1<<0) | 57 | #define IORESOURCE_IRQ_HIGHEDGE (1<<0) |
| 58 | #define IORESOURCE_IRQ_LOWEDGE (1<<1) | 58 | #define IORESOURCE_IRQ_LOWEDGE (1<<1) |
| 59 | #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) | 59 | #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) |
| 60 | #define IORESOURCE_IRQ_LOWLEVEL (1<<3) | 60 | #define IORESOURCE_IRQ_LOWLEVEL (1<<3) |
| 61 | #define IORESOURCE_IRQ_SHAREABLE (1<<4) | 61 | #define IORESOURCE_IRQ_SHAREABLE (1<<4) |
| 62 | 62 | ||
| 63 | /* ISA PnP DMA specific bits (IORESOURCE_BITS) */ | 63 | /* PnP DMA specific bits (IORESOURCE_BITS) */ |
| 64 | #define IORESOURCE_DMA_TYPE_MASK (3<<0) | 64 | #define IORESOURCE_DMA_TYPE_MASK (3<<0) |
| 65 | #define IORESOURCE_DMA_8BIT (0<<0) | 65 | #define IORESOURCE_DMA_8BIT (0<<0) |
| 66 | #define IORESOURCE_DMA_8AND16BIT (1<<0) | 66 | #define IORESOURCE_DMA_8AND16BIT (1<<0) |
| @@ -76,7 +76,7 @@ struct resource_list { | |||
| 76 | #define IORESOURCE_DMA_TYPEB (2<<6) | 76 | #define IORESOURCE_DMA_TYPEB (2<<6) |
| 77 | #define IORESOURCE_DMA_TYPEF (3<<6) | 77 | #define IORESOURCE_DMA_TYPEF (3<<6) |
| 78 | 78 | ||
| 79 | /* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */ | 79 | /* PnP memory I/O specific bits (IORESOURCE_BITS) */ |
| 80 | #define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */ | 80 | #define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */ |
| 81 | #define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */ | 81 | #define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */ |
| 82 | #define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */ | 82 | #define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */ |
