diff options
| -rw-r--r-- | arch/x86/kernel/acpi/boot.c | 22 | ||||
| -rw-r--r-- | drivers/acpi/acpi_pad.c | 37 | ||||
| -rw-r--r-- | drivers/acpi/bus.c | 7 | ||||
| -rw-r--r-- | drivers/acpi/ec.c | 126 | ||||
| -rw-r--r-- | drivers/acpi/pci_link.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/pci_root.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/power.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/power_meter.c | 4 | ||||
| -rw-r--r-- | drivers/acpi/processor_idle.c | 64 | ||||
| -rw-r--r-- | drivers/acpi/processor_pdc.c | 32 | ||||
| -rw-r--r-- | drivers/acpi/processor_thermal.c | 3 | ||||
| -rw-r--r-- | drivers/acpi/sbs.c | 3 | ||||
| -rw-r--r-- | drivers/acpi/sbshc.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 43 | ||||
| -rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 298 | ||||
| -rw-r--r-- | drivers/platform/x86/sony-laptop.c | 9 | ||||
| -rw-r--r-- | include/acpi/platform/aclinux.h | 2 | ||||
| -rw-r--r-- | include/linux/acpi.h | 6 | 
19 files changed, 396 insertions, 269 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fb1035cd9a6a..036d28adf59d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c  | |||
| @@ -1529,16 +1529,10 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { | |||
| 1529 | * if acpi_blacklisted() acpi_disabled = 1; | 1529 | * if acpi_blacklisted() acpi_disabled = 1; | 
| 1530 | * acpi_irq_model=... | 1530 | * acpi_irq_model=... | 
| 1531 | * ... | 1531 | * ... | 
| 1532 | * | ||
| 1533 | * return value: (currently ignored) | ||
| 1534 | * 0: success | ||
| 1535 | * !0: failure | ||
| 1536 | */ | 1532 | */ | 
| 1537 | 1533 | ||
| 1538 | int __init acpi_boot_table_init(void) | 1534 | void __init acpi_boot_table_init(void) | 
| 1539 | { | 1535 | { | 
| 1540 | int error; | ||
| 1541 | |||
| 1542 | dmi_check_system(acpi_dmi_table); | 1536 | dmi_check_system(acpi_dmi_table); | 
| 1543 | 1537 | ||
| 1544 | /* | 1538 | /* | 
| @@ -1546,15 +1540,14 @@ int __init acpi_boot_table_init(void) | |||
| 1546 | * One exception: acpi=ht continues far enough to enumerate LAPICs | 1540 | * One exception: acpi=ht continues far enough to enumerate LAPICs | 
| 1547 | */ | 1541 | */ | 
| 1548 | if (acpi_disabled && !acpi_ht) | 1542 | if (acpi_disabled && !acpi_ht) | 
| 1549 | return 1; | 1543 | return; | 
| 1550 | 1544 | ||
| 1551 | /* | 1545 | /* | 
| 1552 | * Initialize the ACPI boot-time table parser. | 1546 | * Initialize the ACPI boot-time table parser. | 
| 1553 | */ | 1547 | */ | 
| 1554 | error = acpi_table_init(); | 1548 | if (acpi_table_init()) { | 
| 1555 | if (error) { | ||
| 1556 | disable_acpi(); | 1549 | disable_acpi(); | 
| 1557 | return error; | 1550 | return; | 
| 1558 | } | 1551 | } | 
| 1559 | 1552 | ||
| 1560 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); | 1553 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); | 
| @@ -1562,18 +1555,15 @@ int __init acpi_boot_table_init(void) | |||
| 1562 | /* | 1555 | /* | 
| 1563 | * blacklist may disable ACPI entirely | 1556 | * blacklist may disable ACPI entirely | 
| 1564 | */ | 1557 | */ | 
| 1565 | error = acpi_blacklisted(); | 1558 | if (acpi_blacklisted()) { | 
| 1566 | if (error) { | ||
| 1567 | if (acpi_force) { | 1559 | if (acpi_force) { | 
| 1568 | printk(KERN_WARNING PREFIX "acpi=force override\n"); | 1560 | printk(KERN_WARNING PREFIX "acpi=force override\n"); | 
| 1569 | } else { | 1561 | } else { | 
| 1570 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); | 1562 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); | 
| 1571 | disable_acpi(); | 1563 | disable_acpi(); | 
| 1572 | return error; | 1564 | return; | 
| 1573 | } | 1565 | } | 
| 1574 | } | 1566 | } | 
| 1575 | |||
| 1576 | return 0; | ||
| 1577 | } | 1567 | } | 
| 1578 | 1568 | ||
| 1579 | int __init early_acpi_boot_init(void) | 1569 | int __init early_acpi_boot_init(void) | 
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 97991ac6f5fc..7e52295f1ecc 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c  | |||
| @@ -208,7 +208,7 @@ static int power_saving_thread(void *data) | |||
| 208 | * the mechanism only works when all CPUs have RT task running, | 208 | * the mechanism only works when all CPUs have RT task running, | 
| 209 | * as if one CPU hasn't RT task, RT task from other CPUs will | 209 | * as if one CPU hasn't RT task, RT task from other CPUs will | 
| 210 | * borrow CPU time from this CPU and cause RT task use > 95% | 210 | * borrow CPU time from this CPU and cause RT task use > 95% | 
| 211 | * CPU time. To make 'avoid staration' work, takes a nap here. | 211 | * CPU time. To make 'avoid starvation' work, takes a nap here. | 
| 212 | */ | 212 | */ | 
| 213 | if (do_sleep) | 213 | if (do_sleep) | 
| 214 | schedule_timeout_killable(HZ * idle_pct / 100); | 214 | schedule_timeout_killable(HZ * idle_pct / 100); | 
| @@ -222,14 +222,18 @@ static struct task_struct *ps_tsks[NR_CPUS]; | |||
| 222 | static unsigned int ps_tsk_num; | 222 | static unsigned int ps_tsk_num; | 
| 223 | static int create_power_saving_task(void) | 223 | static int create_power_saving_task(void) | 
| 224 | { | 224 | { | 
| 225 | int rc = -ENOMEM; | ||
| 226 | |||
| 225 | ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, | 227 | ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, | 
| 226 | (void *)(unsigned long)ps_tsk_num, | 228 | (void *)(unsigned long)ps_tsk_num, | 
| 227 | "power_saving/%d", ps_tsk_num); | 229 | "power_saving/%d", ps_tsk_num); | 
| 228 | if (ps_tsks[ps_tsk_num]) { | 230 | rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; | 
| 231 | if (!rc) | ||
| 229 | ps_tsk_num++; | 232 | ps_tsk_num++; | 
| 230 | return 0; | 233 | else | 
| 231 | } | 234 | ps_tsks[ps_tsk_num] = NULL; | 
| 232 | return -EINVAL; | 235 | |
| 236 | return rc; | ||
| 233 | } | 237 | } | 
| 234 | 238 | ||
| 235 | static void destroy_power_saving_task(void) | 239 | static void destroy_power_saving_task(void) | 
| @@ -237,6 +241,7 @@ static void destroy_power_saving_task(void) | |||
| 237 | if (ps_tsk_num > 0) { | 241 | if (ps_tsk_num > 0) { | 
| 238 | ps_tsk_num--; | 242 | ps_tsk_num--; | 
| 239 | kthread_stop(ps_tsks[ps_tsk_num]); | 243 | kthread_stop(ps_tsks[ps_tsk_num]); | 
| 244 | ps_tsks[ps_tsk_num] = NULL; | ||
| 240 | } | 245 | } | 
| 241 | } | 246 | } | 
| 242 | 247 | ||
| @@ -253,7 +258,7 @@ static void set_power_saving_task_num(unsigned int num) | |||
| 253 | } | 258 | } | 
| 254 | } | 259 | } | 
| 255 | 260 | ||
| 256 | static int acpi_pad_idle_cpus(unsigned int num_cpus) | 261 | static void acpi_pad_idle_cpus(unsigned int num_cpus) | 
| 257 | { | 262 | { | 
| 258 | get_online_cpus(); | 263 | get_online_cpus(); | 
| 259 | 264 | ||
| @@ -261,7 +266,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus) | |||
| 261 | set_power_saving_task_num(num_cpus); | 266 | set_power_saving_task_num(num_cpus); | 
| 262 | 267 | ||
| 263 | put_online_cpus(); | 268 | put_online_cpus(); | 
| 264 | return 0; | ||
| 265 | } | 269 | } | 
| 266 | 270 | ||
| 267 | static uint32_t acpi_pad_idle_cpus_num(void) | 271 | static uint32_t acpi_pad_idle_cpus_num(void) | 
| @@ -369,19 +373,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) | |||
| 369 | static int acpi_pad_pur(acpi_handle handle, int *num_cpus) | 373 | static int acpi_pad_pur(acpi_handle handle, int *num_cpus) | 
| 370 | { | 374 | { | 
| 371 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 375 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 
| 372 | acpi_status status; | ||
| 373 | union acpi_object *package; | 376 | union acpi_object *package; | 
| 374 | int rev, num, ret = -EINVAL; | 377 | int rev, num, ret = -EINVAL; | 
| 375 | 378 | ||
| 376 | status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); | 379 | if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) | 
| 377 | if (ACPI_FAILURE(status)) | 380 | return -EINVAL; | 
| 381 | |||
| 382 | if (!buffer.length || !buffer.pointer) | ||
| 378 | return -EINVAL; | 383 | return -EINVAL; | 
| 384 | |||
| 379 | package = buffer.pointer; | 385 | package = buffer.pointer; | 
| 380 | if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) | 386 | if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) | 
| 381 | goto out; | 387 | goto out; | 
| 382 | rev = package->package.elements[0].integer.value; | 388 | rev = package->package.elements[0].integer.value; | 
| 383 | num = package->package.elements[1].integer.value; | 389 | num = package->package.elements[1].integer.value; | 
| 384 | if (rev != 1) | 390 | if (rev != 1 || num < 0) | 
| 385 | goto out; | 391 | goto out; | 
| 386 | *num_cpus = num; | 392 | *num_cpus = num; | 
| 387 | ret = 0; | 393 | ret = 0; | 
| @@ -410,7 +416,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat, | |||
| 410 | 416 | ||
| 411 | static void acpi_pad_handle_notify(acpi_handle handle) | 417 | static void acpi_pad_handle_notify(acpi_handle handle) | 
| 412 | { | 418 | { | 
| 413 | int num_cpus, ret; | 419 | int num_cpus; | 
| 414 | uint32_t idle_cpus; | 420 | uint32_t idle_cpus; | 
| 415 | 421 | ||
| 416 | mutex_lock(&isolated_cpus_lock); | 422 | mutex_lock(&isolated_cpus_lock); | 
| @@ -418,12 +424,9 @@ static void acpi_pad_handle_notify(acpi_handle handle) | |||
| 418 | mutex_unlock(&isolated_cpus_lock); | 424 | mutex_unlock(&isolated_cpus_lock); | 
| 419 | return; | 425 | return; | 
| 420 | } | 426 | } | 
| 421 | ret = acpi_pad_idle_cpus(num_cpus); | 427 | acpi_pad_idle_cpus(num_cpus); | 
| 422 | idle_cpus = acpi_pad_idle_cpus_num(); | 428 | idle_cpus = acpi_pad_idle_cpus_num(); | 
| 423 | if (!ret) | 429 | acpi_pad_ost(handle, 0, idle_cpus); | 
| 424 | acpi_pad_ost(handle, 0, idle_cpus); | ||
| 425 | else | ||
| 426 | acpi_pad_ost(handle, 1, 0); | ||
| 427 | mutex_unlock(&isolated_cpus_lock); | 430 | mutex_unlock(&isolated_cpus_lock); | 
| 428 | } | 431 | } | 
| 429 | 432 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cf761b904e4a..a52126e46307 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c  | |||
| @@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void) | |||
| 490 | 490 | ||
| 491 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 491 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 
| 492 | capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ | 492 | capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ | 
| 493 | #ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR | 493 | #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ | 
| 494 | defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) | ||
| 494 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; | 495 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; | 
| 495 | #endif | 496 | #endif | 
| 497 | |||
| 498 | #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) | ||
| 499 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; | ||
| 500 | #endif | ||
| 496 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) | 501 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) | 
| 497 | return; | 502 | return; | 
| 498 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) | 503 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) | 
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fd1801bdee66..d6471bb6852f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c  | |||
| @@ -201,14 +201,13 @@ unlock: | |||
| 201 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 201 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 
| 202 | } | 202 | } | 
| 203 | 203 | ||
| 204 | static void acpi_ec_gpe_query(void *ec_cxt); | 204 | static int acpi_ec_sync_query(struct acpi_ec *ec); | 
| 205 | 205 | ||
| 206 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | 206 | static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) | 
| 207 | { | 207 | { | 
| 208 | if (state & ACPI_EC_FLAG_SCI) { | 208 | if (state & ACPI_EC_FLAG_SCI) { | 
| 209 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) | 209 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) | 
| 210 | return acpi_os_execute(OSL_EC_BURST_HANDLER, | 210 | return acpi_ec_sync_query(ec); | 
| 211 | acpi_ec_gpe_query, ec); | ||
| 212 | } | 211 | } | 
| 213 | return 0; | 212 | return 0; | 
| 214 | } | 213 | } | 
| @@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 249 | { | 248 | { | 
| 250 | unsigned long tmp; | 249 | unsigned long tmp; | 
| 251 | int ret = 0; | 250 | int ret = 0; | 
| 252 | pr_debug(PREFIX "transaction start\n"); | ||
| 253 | /* disable GPE during transaction if storm is detected */ | ||
| 254 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
| 255 | acpi_disable_gpe(NULL, ec->gpe); | ||
| 256 | } | ||
| 257 | if (EC_FLAGS_MSI) | 251 | if (EC_FLAGS_MSI) | 
| 258 | udelay(ACPI_EC_MSI_UDELAY); | 252 | udelay(ACPI_EC_MSI_UDELAY); | 
| 259 | /* start transaction */ | 253 | /* start transaction */ | 
| @@ -265,20 +259,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 265 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 259 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 
| 266 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 260 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 
| 267 | ret = ec_poll(ec); | 261 | ret = ec_poll(ec); | 
| 268 | pr_debug(PREFIX "transaction end\n"); | ||
| 269 | spin_lock_irqsave(&ec->curr_lock, tmp); | 262 | spin_lock_irqsave(&ec->curr_lock, tmp); | 
| 270 | ec->curr = NULL; | 263 | ec->curr = NULL; | 
| 271 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 264 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 
| 272 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
| 273 | /* check if we received SCI during transaction */ | ||
| 274 | ec_check_sci(ec, acpi_ec_read_status(ec)); | ||
| 275 | /* it is safe to enable GPE outside of transaction */ | ||
| 276 | acpi_enable_gpe(NULL, ec->gpe); | ||
| 277 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { | ||
| 278 | pr_info(PREFIX "GPE storm detected, " | ||
| 279 | "transactions will use polling mode\n"); | ||
| 280 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | ||
| 281 | } | ||
| 282 | return ret; | 265 | return ret; | 
| 283 | } | 266 | } | 
| 284 | 267 | ||
| @@ -321,7 +304,26 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
| 321 | status = -ETIME; | 304 | status = -ETIME; | 
| 322 | goto end; | 305 | goto end; | 
| 323 | } | 306 | } | 
| 307 | pr_debug(PREFIX "transaction start\n"); | ||
| 308 | /* disable GPE during transaction if storm is detected */ | ||
| 309 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
| 310 | acpi_disable_gpe(NULL, ec->gpe); | ||
| 311 | } | ||
| 312 | |||
| 324 | status = acpi_ec_transaction_unlocked(ec, t); | 313 | status = acpi_ec_transaction_unlocked(ec, t); | 
| 314 | |||
| 315 | /* check if we received SCI during transaction */ | ||
| 316 | ec_check_sci_sync(ec, acpi_ec_read_status(ec)); | ||
| 317 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
| 318 | msleep(1); | ||
| 319 | /* it is safe to enable GPE outside of transaction */ | ||
| 320 | acpi_enable_gpe(NULL, ec->gpe); | ||
| 321 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { | ||
| 322 | pr_info(PREFIX "GPE storm detected, " | ||
| 323 | "transactions will use polling mode\n"); | ||
| 324 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | ||
| 325 | } | ||
| 326 | pr_debug(PREFIX "transaction end\n"); | ||
| 325 | end: | 327 | end: | 
| 326 | if (ec->global_lock) | 328 | if (ec->global_lock) | 
| 327 | acpi_release_global_lock(glk); | 329 | acpi_release_global_lock(glk); | 
| @@ -443,7 +445,7 @@ int ec_transaction(u8 command, | |||
| 443 | 445 | ||
| 444 | EXPORT_SYMBOL(ec_transaction); | 446 | EXPORT_SYMBOL(ec_transaction); | 
| 445 | 447 | ||
| 446 | static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | 448 | static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) | 
| 447 | { | 449 | { | 
| 448 | int result; | 450 | int result; | 
| 449 | u8 d; | 451 | u8 d; | 
| @@ -452,20 +454,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | |||
| 452 | .wlen = 0, .rlen = 1}; | 454 | .wlen = 0, .rlen = 1}; | 
| 453 | if (!ec || !data) | 455 | if (!ec || !data) | 
| 454 | return -EINVAL; | 456 | return -EINVAL; | 
| 455 | |||
| 456 | /* | 457 | /* | 
| 457 | * Query the EC to find out which _Qxx method we need to evaluate. | 458 | * Query the EC to find out which _Qxx method we need to evaluate. | 
| 458 | * Note that successful completion of the query causes the ACPI_EC_SCI | 459 | * Note that successful completion of the query causes the ACPI_EC_SCI | 
| 459 | * bit to be cleared (and thus clearing the interrupt source). | 460 | * bit to be cleared (and thus clearing the interrupt source). | 
| 460 | */ | 461 | */ | 
| 461 | 462 | result = acpi_ec_transaction_unlocked(ec, &t); | |
| 462 | result = acpi_ec_transaction(ec, &t); | ||
| 463 | if (result) | 463 | if (result) | 
| 464 | return result; | 464 | return result; | 
| 465 | |||
| 466 | if (!d) | 465 | if (!d) | 
| 467 | return -ENODATA; | 466 | return -ENODATA; | 
| 468 | |||
| 469 | *data = d; | 467 | *data = d; | 
| 470 | return 0; | 468 | return 0; | 
| 471 | } | 469 | } | 
| @@ -509,43 +507,79 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) | |||
| 509 | 507 | ||
| 510 | EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); | 508 | EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); | 
| 511 | 509 | ||
| 512 | static void acpi_ec_gpe_query(void *ec_cxt) | 510 | static void acpi_ec_run(void *cxt) | 
| 513 | { | 511 | { | 
| 514 | struct acpi_ec *ec = ec_cxt; | 512 | struct acpi_ec_query_handler *handler = cxt; | 
| 515 | u8 value = 0; | 513 | if (!handler) | 
| 516 | struct acpi_ec_query_handler *handler, copy; | ||
| 517 | |||
| 518 | if (!ec || acpi_ec_query(ec, &value)) | ||
| 519 | return; | 514 | return; | 
| 520 | mutex_lock(&ec->lock); | 515 | pr_debug(PREFIX "start query execution\n"); | 
| 516 | if (handler->func) | ||
| 517 | handler->func(handler->data); | ||
| 518 | else if (handler->handle) | ||
| 519 | acpi_evaluate_object(handler->handle, NULL, NULL, NULL); | ||
| 520 | pr_debug(PREFIX "stop query execution\n"); | ||
| 521 | kfree(handler); | ||
| 522 | } | ||
| 523 | |||
| 524 | static int acpi_ec_sync_query(struct acpi_ec *ec) | ||
| 525 | { | ||
| 526 | u8 value = 0; | ||
| 527 | int status; | ||
| 528 | struct acpi_ec_query_handler *handler, *copy; | ||
| 529 | if ((status = acpi_ec_query_unlocked(ec, &value))) | ||
| 530 | return status; | ||
| 521 | list_for_each_entry(handler, &ec->list, node) { | 531 | list_for_each_entry(handler, &ec->list, node) { | 
| 522 | if (value == handler->query_bit) { | 532 | if (value == handler->query_bit) { | 
| 523 | /* have custom handler for this bit */ | 533 | /* have custom handler for this bit */ | 
| 524 | memcpy(©, handler, sizeof(copy)); | 534 | copy = kmalloc(sizeof(*handler), GFP_KERNEL); | 
| 525 | mutex_unlock(&ec->lock); | 535 | if (!copy) | 
| 526 | if (copy.func) { | 536 | return -ENOMEM; | 
| 527 | copy.func(copy.data); | 537 | memcpy(copy, handler, sizeof(*copy)); | 
| 528 | } else if (copy.handle) { | 538 | pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); | 
| 529 | acpi_evaluate_object(copy.handle, NULL, NULL, NULL); | 539 | return acpi_os_execute((copy->func) ? | 
| 530 | } | 540 | OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, | 
| 531 | return; | 541 | acpi_ec_run, copy); | 
| 532 | } | 542 | } | 
| 533 | } | 543 | } | 
| 544 | return 0; | ||
| 545 | } | ||
| 546 | |||
| 547 | static void acpi_ec_gpe_query(void *ec_cxt) | ||
| 548 | { | ||
| 549 | struct acpi_ec *ec = ec_cxt; | ||
| 550 | if (!ec) | ||
| 551 | return; | ||
| 552 | mutex_lock(&ec->lock); | ||
| 553 | acpi_ec_sync_query(ec); | ||
| 534 | mutex_unlock(&ec->lock); | 554 | mutex_unlock(&ec->lock); | 
| 535 | } | 555 | } | 
| 536 | 556 | ||
| 557 | static void acpi_ec_gpe_query(void *ec_cxt); | ||
| 558 | |||
| 559 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | ||
| 560 | { | ||
| 561 | if (state & ACPI_EC_FLAG_SCI) { | ||
| 562 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { | ||
| 563 | pr_debug(PREFIX "push gpe query to the queue\n"); | ||
| 564 | return acpi_os_execute(OSL_NOTIFY_HANDLER, | ||
| 565 | acpi_ec_gpe_query, ec); | ||
| 566 | } | ||
| 567 | } | ||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 537 | static u32 acpi_ec_gpe_handler(void *data) | 571 | static u32 acpi_ec_gpe_handler(void *data) | 
| 538 | { | 572 | { | 
| 539 | struct acpi_ec *ec = data; | 573 | struct acpi_ec *ec = data; | 
| 540 | u8 status; | ||
| 541 | 574 | ||
| 542 | pr_debug(PREFIX "~~~> interrupt\n"); | 575 | pr_debug(PREFIX "~~~> interrupt\n"); | 
| 543 | status = acpi_ec_read_status(ec); | ||
| 544 | 576 | ||
| 545 | advance_transaction(ec, status); | 577 | advance_transaction(ec, acpi_ec_read_status(ec)); | 
| 546 | if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) | 578 | if (ec_transaction_done(ec) && | 
| 579 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
| 547 | wake_up(&ec->wait); | 580 | wake_up(&ec->wait); | 
| 548 | ec_check_sci(ec, status); | 581 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 
| 582 | } | ||
| 549 | return ACPI_INTERRUPT_HANDLED; | 583 | return ACPI_INTERRUPT_HANDLED; | 
| 550 | } | 584 | } | 
| 551 | 585 | ||
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 394ae89409c2..04b0f007c9b7 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c  | |||
| @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link"); | |||
| 56 | static int acpi_pci_link_add(struct acpi_device *device); | 56 | static int acpi_pci_link_add(struct acpi_device *device); | 
| 57 | static int acpi_pci_link_remove(struct acpi_device *device, int type); | 57 | static int acpi_pci_link_remove(struct acpi_device *device, int type); | 
| 58 | 58 | ||
| 59 | static struct acpi_device_id link_device_ids[] = { | 59 | static const struct acpi_device_id link_device_ids[] = { | 
| 60 | {"PNP0C0F", 0}, | 60 | {"PNP0C0F", 0}, | 
| 61 | {"", 0}, | 61 | {"", 0}, | 
| 62 | }; | 62 | }; | 
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 101cce3681d1..64f55b6db73c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c  | |||
| @@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device); | |||
| 46 | static int acpi_pci_root_remove(struct acpi_device *device, int type); | 46 | static int acpi_pci_root_remove(struct acpi_device *device, int type); | 
| 47 | static int acpi_pci_root_start(struct acpi_device *device); | 47 | static int acpi_pci_root_start(struct acpi_device *device); | 
| 48 | 48 | ||
| 49 | static struct acpi_device_id root_device_ids[] = { | 49 | static const struct acpi_device_id root_device_ids[] = { | 
| 50 | {"PNP0A03", 0}, | 50 | {"PNP0A03", 0}, | 
| 51 | {"", 0}, | 51 | {"", 0}, | 
| 52 | }; | 52 | }; | 
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 22b297916519..0f30c3c1eea4 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c  | |||
| @@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type); | |||
| 65 | static int acpi_power_resume(struct acpi_device *device); | 65 | static int acpi_power_resume(struct acpi_device *device); | 
| 66 | static int acpi_power_open_fs(struct inode *inode, struct file *file); | 66 | static int acpi_power_open_fs(struct inode *inode, struct file *file); | 
| 67 | 67 | ||
| 68 | static struct acpi_device_id power_device_ids[] = { | 68 | static const struct acpi_device_id power_device_ids[] = { | 
| 69 | {ACPI_POWER_HID, 0}, | 69 | {ACPI_POWER_HID, 0}, | 
| 70 | {"", 0}, | 70 | {"", 0}, | 
| 71 | }; | 71 | }; | 
diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index 2ef7030a0c28..dc4ffadf8122 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c  | |||
| @@ -64,7 +64,7 @@ static int can_cap_in_hardware(void) | |||
| 64 | return force_cap_on || cap_in_hardware; | 64 | return force_cap_on || cap_in_hardware; | 
| 65 | } | 65 | } | 
| 66 | 66 | ||
| 67 | static struct acpi_device_id power_meter_ids[] = { | 67 | static const struct acpi_device_id power_meter_ids[] = { | 
| 68 | {"ACPI000D", 0}, | 68 | {"ACPI000D", 0}, | 
| 69 | {"", 0}, | 69 | {"", 0}, | 
| 70 | }; | 70 | }; | 
| @@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) | |||
| 534 | 534 | ||
| 535 | kfree(resource->domain_devices); | 535 | kfree(resource->domain_devices); | 
| 536 | kobject_put(resource->holders_dir); | 536 | kobject_put(resource->holders_dir); | 
| 537 | resource->num_domain_devices = 0; | ||
| 537 | } | 538 | } | 
| 538 | 539 | ||
| 539 | static int read_domain_devices(struct acpi_power_meter_resource *resource) | 540 | static int read_domain_devices(struct acpi_power_meter_resource *resource) | 
| @@ -740,7 +741,6 @@ skip_unsafe_cap: | |||
| 740 | 741 | ||
| 741 | return res; | 742 | return res; | 
| 742 | error: | 743 | error: | 
| 743 | remove_domain_devices(resource); | ||
| 744 | remove_attrs(resource); | 744 | remove_attrs(resource); | 
| 745 | return res; | 745 | return res; | 
| 746 | } | 746 | } | 
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d1676b1754d9..7c0441f63b39 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c  | |||
| @@ -305,6 +305,28 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
| 305 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; | 305 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; | 
| 306 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; | 306 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; | 
| 307 | 307 | ||
| 308 | /* | ||
| 309 | * FADT specified C2 latency must be less than or equal to | ||
| 310 | * 100 microseconds. | ||
| 311 | */ | ||
| 312 | if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | ||
| 313 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 314 | "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); | ||
| 315 | /* invalidate C2 */ | ||
| 316 | pr->power.states[ACPI_STATE_C2].address = 0; | ||
| 317 | } | ||
| 318 | |||
| 319 | /* | ||
| 320 | * FADT supplied C3 latency must be less than or equal to | ||
| 321 | * 1000 microseconds. | ||
| 322 | */ | ||
| 323 | if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | ||
| 324 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 325 | "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); | ||
| 326 | /* invalidate C3 */ | ||
| 327 | pr->power.states[ACPI_STATE_C3].address = 0; | ||
| 328 | } | ||
| 329 | |||
| 308 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 330 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 
| 309 | "lvl2[0x%08x] lvl3[0x%08x]\n", | 331 | "lvl2[0x%08x] lvl3[0x%08x]\n", | 
| 310 | pr->power.states[ACPI_STATE_C2].address, | 332 | pr->power.states[ACPI_STATE_C2].address, | 
| @@ -494,33 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
| 494 | return status; | 516 | return status; | 
| 495 | } | 517 | } | 
| 496 | 518 | ||
| 497 | static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | ||
| 498 | { | ||
| 499 | |||
| 500 | if (!cx->address) | ||
| 501 | return; | ||
| 502 | |||
| 503 | /* | ||
| 504 | * C2 latency must be less than or equal to 100 | ||
| 505 | * microseconds. | ||
| 506 | */ | ||
| 507 | else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | ||
| 508 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 509 | "latency too large [%d]\n", cx->latency)); | ||
| 510 | return; | ||
| 511 | } | ||
| 512 | |||
| 513 | /* | ||
| 514 | * Otherwise we've met all of our C2 requirements. | ||
| 515 | * Normalize the C2 latency to expidite policy | ||
| 516 | */ | ||
| 517 | cx->valid = 1; | ||
| 518 | |||
| 519 | cx->latency_ticks = cx->latency; | ||
| 520 | |||
| 521 | return; | ||
| 522 | } | ||
| 523 | |||
| 524 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | 519 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | 
| 525 | struct acpi_processor_cx *cx) | 520 | struct acpi_processor_cx *cx) | 
| 526 | { | 521 | { | 
| @@ -532,16 +527,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
| 532 | return; | 527 | return; | 
| 533 | 528 | ||
| 534 | /* | 529 | /* | 
| 535 | * C3 latency must be less than or equal to 1000 | ||
| 536 | * microseconds. | ||
| 537 | */ | ||
| 538 | else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | ||
| 539 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 540 | "latency too large [%d]\n", cx->latency)); | ||
| 541 | return; | ||
| 542 | } | ||
| 543 | |||
| 544 | /* | ||
| 545 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) | 530 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) | 
| 546 | * DMA transfers are used by any ISA device to avoid livelock. | 531 | * DMA transfers are used by any ISA device to avoid livelock. | 
| 547 | * Note that we could disable Type-F DMA (as recommended by | 532 | * Note that we could disable Type-F DMA (as recommended by | 
| @@ -629,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 629 | break; | 614 | break; | 
| 630 | 615 | ||
| 631 | case ACPI_STATE_C2: | 616 | case ACPI_STATE_C2: | 
| 632 | acpi_processor_power_verify_c2(cx); | 617 | if (!cx->address) | 
| 618 | break; | ||
| 619 | cx->valid = 1; | ||
| 620 | cx->latency_ticks = cx->latency; /* Normalize latency */ | ||
| 633 | break; | 621 | break; | 
| 634 | 622 | ||
| 635 | case ACPI_STATE_C3: | 623 | case ACPI_STATE_C3: | 
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf30..7247819dbd80 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c  | |||
| @@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle) | |||
| 144 | } | 144 | } | 
| 145 | EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); | 145 | EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); | 
| 146 | 146 | ||
| 147 | static int early_pdc_optin; | ||
| 148 | static int set_early_pdc_optin(const struct dmi_system_id *id) | ||
| 149 | { | ||
| 150 | early_pdc_optin = 1; | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { | ||
| 155 | { | ||
| 156 | set_early_pdc_optin, "HP Envy", { | ||
| 157 | DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), | ||
| 158 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, | ||
| 159 | { | ||
| 160 | set_early_pdc_optin, "HP Pavilion dv6", { | ||
| 161 | DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), | ||
| 162 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, | ||
| 163 | { | ||
| 164 | set_early_pdc_optin, "HP Pavilion dv7", { | ||
| 165 | DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), | ||
| 166 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, | ||
| 167 | {}, | ||
| 168 | }; | ||
| 169 | |||
| 147 | static acpi_status | 170 | static acpi_status | 
| 148 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | 171 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | 
| 149 | { | 172 | { | 
| @@ -151,7 +174,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 151 | return AE_OK; | 174 | return AE_OK; | 
| 152 | } | 175 | } | 
| 153 | 176 | ||
| 154 | void acpi_early_processor_set_pdc(void) | 177 | void __init acpi_early_processor_set_pdc(void) | 
| 155 | { | 178 | { | 
| 156 | /* | 179 | /* | 
| 157 | * Check whether the system is DMI table. If yes, OSPM | 180 | * Check whether the system is DMI table. If yes, OSPM | 
| @@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void) | |||
| 159 | */ | 182 | */ | 
| 160 | dmi_check_system(processor_idle_dmi_table); | 183 | dmi_check_system(processor_idle_dmi_table); | 
| 161 | 184 | ||
| 185 | /* | ||
| 186 | * Allow systems to opt-in to early _PDC evaluation. | ||
| 187 | */ | ||
| 188 | dmi_check_system(early_pdc_optin_table); | ||
| 189 | if (!early_pdc_optin) | ||
| 190 | return; | ||
| 191 | |||
| 162 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | 192 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | 
| 163 | ACPI_UINT32_MAX, | 193 | ACPI_UINT32_MAX, | 
| 164 | early_init_pdc, NULL, NULL, NULL); | 194 | early_init_pdc, NULL, NULL, NULL); | 
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 140c5c5b423c..6deafb4aa0da 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c  | |||
| @@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { | |||
| 443 | #ifdef CONFIG_ACPI_PROCFS | 443 | #ifdef CONFIG_ACPI_PROCFS | 
| 444 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) | 444 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) | 
| 445 | { | 445 | { | 
| 446 | struct acpi_processor *pr = (struct acpi_processor *)seq->private; | 446 | struct acpi_processor *pr = seq->private; | 
| 447 | |||
| 448 | 447 | ||
| 449 | if (!pr) | 448 | if (!pr) | 
| 450 | goto end; | 449 | goto end; | 
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 52b9db8afc20..b16ddbf23a9c 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c  | |||
| @@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
| 822 | 822 | ||
| 823 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 823 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 
| 824 | { | 824 | { | 
| 825 | #if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) | ||
| 825 | struct acpi_battery *battery = &sbs->battery[id]; | 826 | struct acpi_battery *battery = &sbs->battery[id]; | 
| 827 | #endif | ||
| 828 | |||
| 826 | #ifdef CONFIG_ACPI_SYSFS_POWER | 829 | #ifdef CONFIG_ACPI_SYSFS_POWER | 
| 827 | if (battery->bat.dev) { | 830 | if (battery->bat.dev) { | 
| 828 | if (battery->have_sysfs_alarm) | 831 | if (battery->have_sysfs_alarm) | 
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d9339806df45..fd09229282ea 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c  | |||
| @@ -242,7 +242,7 @@ static int smbus_alarm(void *context) | |||
| 242 | case ACPI_SBS_CHARGER: | 242 | case ACPI_SBS_CHARGER: | 
| 243 | case ACPI_SBS_MANAGER: | 243 | case ACPI_SBS_MANAGER: | 
| 244 | case ACPI_SBS_BATTERY: | 244 | case ACPI_SBS_BATTERY: | 
| 245 | acpi_os_execute(OSL_GPE_HANDLER, | 245 | acpi_os_execute(OSL_NOTIFY_HANDLER, | 
| 246 | acpi_smbus_callback, hc); | 246 | acpi_smbus_callback, hc); | 
| 247 | default:; | 247 | default:; | 
| 248 | } | 248 | } | 
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 72e76b4b6538..b765790b32be 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c  | |||
| @@ -78,6 +78,13 @@ MODULE_LICENSE("GPL"); | |||
| 78 | static int brightness_switch_enabled = 1; | 78 | static int brightness_switch_enabled = 1; | 
| 79 | module_param(brightness_switch_enabled, bool, 0644); | 79 | module_param(brightness_switch_enabled, bool, 0644); | 
| 80 | 80 | ||
| 81 | /* | ||
| 82 | * By default, we don't allow duplicate ACPI video bus devices | ||
| 83 | * under the same VGA controller | ||
| 84 | */ | ||
| 85 | static int allow_duplicates; | ||
| 86 | module_param(allow_duplicates, bool, 0644); | ||
| 87 | |||
| 81 | static int register_count = 0; | 88 | static int register_count = 0; | 
| 82 | static int acpi_video_bus_add(struct acpi_device *device); | 89 | static int acpi_video_bus_add(struct acpi_device *device); | 
| 83 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 90 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 
| @@ -2239,11 +2246,47 @@ static int acpi_video_resume(struct acpi_device *device) | |||
| 2239 | return AE_OK; | 2246 | return AE_OK; | 
| 2240 | } | 2247 | } | 
| 2241 | 2248 | ||
| 2249 | static acpi_status | ||
| 2250 | acpi_video_bus_match(acpi_handle handle, u32 level, void *context, | ||
| 2251 | void **return_value) | ||
| 2252 | { | ||
| 2253 | struct acpi_device *device = context; | ||
| 2254 | struct acpi_device *sibling; | ||
| 2255 | int result; | ||
| 2256 | |||
| 2257 | if (handle == device->handle) | ||
| 2258 | return AE_CTRL_TERMINATE; | ||
| 2259 | |||
| 2260 | result = acpi_bus_get_device(handle, &sibling); | ||
| 2261 | if (result) | ||
| 2262 | return AE_OK; | ||
| 2263 | |||
| 2264 | if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) | ||
| 2265 | return AE_ALREADY_EXISTS; | ||
| 2266 | |||
| 2267 | return AE_OK; | ||
| 2268 | } | ||
| 2269 | |||
| 2242 | static int acpi_video_bus_add(struct acpi_device *device) | 2270 | static int acpi_video_bus_add(struct acpi_device *device) | 
| 2243 | { | 2271 | { | 
| 2244 | struct acpi_video_bus *video; | 2272 | struct acpi_video_bus *video; | 
| 2245 | struct input_dev *input; | 2273 | struct input_dev *input; | 
| 2246 | int error; | 2274 | int error; | 
| 2275 | acpi_status status; | ||
| 2276 | |||
| 2277 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, | ||
| 2278 | device->parent->handle, 1, | ||
| 2279 | acpi_video_bus_match, NULL, | ||
| 2280 | device, NULL); | ||
| 2281 | if (status == AE_ALREADY_EXISTS) { | ||
| 2282 | printk(KERN_WARNING FW_BUG | ||
| 2283 | "Duplicate ACPI video bus devices for the" | ||
| 2284 | " same VGA controller, please try module " | ||
| 2285 | "parameter \"video.allow_duplicates=1\"" | ||
| 2286 | "if the current driver doesn't work.\n"); | ||
| 2287 | if (!allow_duplicates) | ||
| 2288 | return -ENODEV; | ||
| 2289 | } | ||
| 2247 | 2290 | ||
| 2248 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 2291 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 
| 2249 | if (!video) | 2292 | if (!video) | 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index db32c25e3605..f526e735c5ab 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig  | |||
| @@ -364,6 +364,7 @@ config EEEPC_LAPTOP | |||
| 364 | select HWMON | 364 | select HWMON | 
| 365 | select LEDS_CLASS | 365 | select LEDS_CLASS | 
| 366 | select NEW_LEDS | 366 | select NEW_LEDS | 
| 367 | select INPUT_SPARSEKMAP | ||
| 367 | ---help--- | 368 | ---help--- | 
| 368 | This driver supports the Fn-Fx keys on Eee PC laptops. | 369 | This driver supports the Fn-Fx keys on Eee PC laptops. | 
| 369 | 370 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5838c69b2fb3..e2be6bb33d92 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c  | |||
| @@ -31,10 +31,12 @@ | |||
| 31 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> | 
| 32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> | 
| 33 | #include <linux/input.h> | 33 | #include <linux/input.h> | 
| 34 | #include <linux/input/sparse-keymap.h> | ||
| 34 | #include <linux/rfkill.h> | 35 | #include <linux/rfkill.h> | 
| 35 | #include <linux/pci.h> | 36 | #include <linux/pci.h> | 
| 36 | #include <linux/pci_hotplug.h> | 37 | #include <linux/pci_hotplug.h> | 
| 37 | #include <linux/leds.h> | 38 | #include <linux/leds.h> | 
| 39 | #include <linux/dmi.h> | ||
| 38 | 40 | ||
| 39 | #define EEEPC_LAPTOP_VERSION "0.1" | 41 | #define EEEPC_LAPTOP_VERSION "0.1" | 
| 40 | #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" | 42 | #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" | 
| @@ -48,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper"); | |||
| 48 | MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); | 50 | MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); | 
| 49 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); | 
| 50 | 52 | ||
| 53 | static bool hotplug_disabled; | ||
| 54 | |||
| 55 | module_param(hotplug_disabled, bool, 0644); | ||
| 56 | MODULE_PARM_DESC(hotplug_disabled, | ||
| 57 | "Disable hotplug for wireless device. " | ||
| 58 | "If your laptop need that, please report to " | ||
| 59 | "acpi4asus-user@lists.sourceforge.net."); | ||
| 60 | |||
| 51 | /* | 61 | /* | 
| 52 | * Definitions for Asus EeePC | 62 | * Definitions for Asus EeePC | 
| 53 | */ | 63 | */ | 
| @@ -120,38 +130,28 @@ static const char *cm_setv[] = { | |||
| 120 | NULL, NULL, "PBPS", "TPDS" | 130 | NULL, NULL, "PBPS", "TPDS" | 
| 121 | }; | 131 | }; | 
| 122 | 132 | ||
| 123 | struct key_entry { | ||
| 124 | char type; | ||
| 125 | u8 code; | ||
| 126 | u16 keycode; | ||
| 127 | }; | ||
| 128 | |||
| 129 | enum { KE_KEY, KE_END }; | ||
| 130 | |||
| 131 | static const struct key_entry eeepc_keymap[] = { | 133 | static const struct key_entry eeepc_keymap[] = { | 
| 132 | /* Sleep already handled via generic ACPI code */ | 134 | { KE_KEY, 0x10, { KEY_WLAN } }, | 
| 133 | {KE_KEY, 0x10, KEY_WLAN }, | 135 | { KE_KEY, 0x11, { KEY_WLAN } }, | 
| 134 | {KE_KEY, 0x11, KEY_WLAN }, | 136 | { KE_KEY, 0x12, { KEY_PROG1 } }, | 
| 135 | {KE_KEY, 0x12, KEY_PROG1 }, | 137 | { KE_KEY, 0x13, { KEY_MUTE } }, | 
| 136 | {KE_KEY, 0x13, KEY_MUTE }, | 138 | { KE_KEY, 0x14, { KEY_VOLUMEDOWN } }, | 
| 137 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, | 139 | { KE_KEY, 0x15, { KEY_VOLUMEUP } }, | 
| 138 | {KE_KEY, 0x15, KEY_VOLUMEUP }, | 140 | { KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, | 
| 139 | {KE_KEY, 0x16, KEY_DISPLAY_OFF }, | 141 | { KE_KEY, 0x1a, { KEY_COFFEE } }, | 
| 140 | {KE_KEY, 0x1a, KEY_COFFEE }, | 142 | { KE_KEY, 0x1b, { KEY_ZOOM } }, | 
| 141 | {KE_KEY, 0x1b, KEY_ZOOM }, | 143 | { KE_KEY, 0x1c, { KEY_PROG2 } }, | 
| 142 | {KE_KEY, 0x1c, KEY_PROG2 }, | 144 | { KE_KEY, 0x1d, { KEY_PROG3 } }, | 
| 143 | {KE_KEY, 0x1d, KEY_PROG3 }, | 145 | { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } }, | 
| 144 | {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, | 146 | { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } }, | 
| 145 | {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, | 147 | { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, | 
| 146 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, | 148 | { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, | 
| 147 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, | 149 | { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, | 
| 148 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, | 150 | { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ | 
| 149 | {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ | 151 | { KE_KEY, 0x38, { KEY_F14 } }, | 
| 150 | {KE_KEY, 0x38, KEY_F14 }, | 152 | { KE_END, 0 }, | 
| 151 | {KE_END, 0}, | ||
| 152 | }; | 153 | }; | 
| 153 | 154 | ||
| 154 | |||
| 155 | /* | 155 | /* | 
| 156 | * This is the main structure, we can use it to store useful information | 156 | * This is the main structure, we can use it to store useful information | 
| 157 | */ | 157 | */ | 
| @@ -159,6 +159,8 @@ struct eeepc_laptop { | |||
| 159 | acpi_handle handle; /* the handle of the acpi device */ | 159 | acpi_handle handle; /* the handle of the acpi device */ | 
| 160 | u32 cm_supported; /* the control methods supported | 160 | u32 cm_supported; /* the control methods supported | 
| 161 | by this BIOS */ | 161 | by this BIOS */ | 
| 162 | bool cpufv_disabled; | ||
| 163 | bool hotplug_disabled; | ||
| 162 | u16 event_count[128]; /* count for each event */ | 164 | u16 event_count[128]; /* count for each event */ | 
| 163 | 165 | ||
| 164 | struct platform_device *platform_device; | 166 | struct platform_device *platform_device; | 
| @@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev, | |||
| 378 | struct eeepc_cpufv c; | 380 | struct eeepc_cpufv c; | 
| 379 | int rv, value; | 381 | int rv, value; | 
| 380 | 382 | ||
| 383 | if (eeepc->cpufv_disabled) | ||
| 384 | return -EPERM; | ||
| 381 | if (get_cpufv(eeepc, &c)) | 385 | if (get_cpufv(eeepc, &c)) | 
| 382 | return -ENODEV; | 386 | return -ENODEV; | 
| 383 | rv = parse_arg(buf, count, &value); | 387 | rv = parse_arg(buf, count, &value); | 
| @@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev, | |||
| 389 | return rv; | 393 | return rv; | 
| 390 | } | 394 | } | 
| 391 | 395 | ||
| 396 | static ssize_t show_cpufv_disabled(struct device *dev, | ||
| 397 | struct device_attribute *attr, | ||
| 398 | char *buf) | ||
| 399 | { | ||
| 400 | struct eeepc_laptop *eeepc = dev_get_drvdata(dev); | ||
| 401 | |||
| 402 | return sprintf(buf, "%d\n", eeepc->cpufv_disabled); | ||
| 403 | } | ||
| 404 | |||
| 405 | static ssize_t store_cpufv_disabled(struct device *dev, | ||
| 406 | struct device_attribute *attr, | ||
| 407 | const char *buf, size_t count) | ||
| 408 | { | ||
| 409 | struct eeepc_laptop *eeepc = dev_get_drvdata(dev); | ||
| 410 | int rv, value; | ||
| 411 | |||
| 412 | rv = parse_arg(buf, count, &value); | ||
| 413 | if (rv < 0) | ||
| 414 | return rv; | ||
| 415 | |||
| 416 | switch (value) { | ||
| 417 | case 0: | ||
| 418 | if (eeepc->cpufv_disabled) | ||
| 419 | pr_warning("cpufv enabled (not officially supported " | ||
| 420 | "on this model)\n"); | ||
| 421 | eeepc->cpufv_disabled = false; | ||
| 422 | return rv; | ||
| 423 | case 1: | ||
| 424 | return -EPERM; | ||
| 425 | default: | ||
| 426 | return -EINVAL; | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | |||
| 392 | static struct device_attribute dev_attr_cpufv = { | 431 | static struct device_attribute dev_attr_cpufv = { | 
| 393 | .attr = { | 432 | .attr = { | 
| 394 | .name = "cpufv", | 433 | .name = "cpufv", | 
| @@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = { | |||
| 404 | .show = show_available_cpufv | 443 | .show = show_available_cpufv | 
| 405 | }; | 444 | }; | 
| 406 | 445 | ||
| 446 | static struct device_attribute dev_attr_cpufv_disabled = { | ||
| 447 | .attr = { | ||
| 448 | .name = "cpufv_disabled", | ||
| 449 | .mode = 0644 }, | ||
| 450 | .show = show_cpufv_disabled, | ||
| 451 | .store = store_cpufv_disabled | ||
| 452 | }; | ||
| 453 | |||
| 454 | |||
| 407 | static struct attribute *platform_attributes[] = { | 455 | static struct attribute *platform_attributes[] = { | 
| 408 | &dev_attr_camera.attr, | 456 | &dev_attr_camera.attr, | 
| 409 | &dev_attr_cardr.attr, | 457 | &dev_attr_cardr.attr, | 
| 410 | &dev_attr_disp.attr, | 458 | &dev_attr_disp.attr, | 
| 411 | &dev_attr_cpufv.attr, | 459 | &dev_attr_cpufv.attr, | 
| 412 | &dev_attr_available_cpufv.attr, | 460 | &dev_attr_available_cpufv.attr, | 
| 461 | &dev_attr_cpufv_disabled.attr, | ||
| 413 | NULL | 462 | NULL | 
| 414 | }; | 463 | }; | 
| 415 | 464 | ||
| @@ -796,6 +845,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) | |||
| 796 | if (result && result != -ENODEV) | 845 | if (result && result != -ENODEV) | 
| 797 | goto exit; | 846 | goto exit; | 
| 798 | 847 | ||
| 848 | if (eeepc->hotplug_disabled) | ||
| 849 | return 0; | ||
| 850 | |||
| 799 | result = eeepc_setup_pci_hotplug(eeepc); | 851 | result = eeepc_setup_pci_hotplug(eeepc); | 
| 800 | /* | 852 | /* | 
| 801 | * If we get -EBUSY then something else is handling the PCI hotplug - | 853 | * If we get -EBUSY then something else is handling the PCI hotplug - | 
| @@ -1090,120 +1142,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) | |||
| 1090 | /* | 1142 | /* | 
| 1091 | * Input device (i.e. hotkeys) | 1143 | * Input device (i.e. hotkeys) | 
| 1092 | */ | 1144 | */ | 
| 1093 | static struct key_entry *eeepc_get_entry_by_scancode( | 1145 | static int eeepc_input_init(struct eeepc_laptop *eeepc) | 
| 1094 | struct eeepc_laptop *eeepc, | ||
| 1095 | int code) | ||
| 1096 | { | 1146 | { | 
| 1097 | struct key_entry *key; | 1147 | struct input_dev *input; | 
| 1148 | int error; | ||
| 1098 | 1149 | ||
| 1099 | for (key = eeepc->keymap; key->type != KE_END; key++) | 1150 | input = input_allocate_device(); | 
| 1100 | if (code == key->code) | 1151 | if (!input) { | 
| 1101 | return key; | 1152 | pr_info("Unable to allocate input device\n"); | 
| 1102 | 1153 | return -ENOMEM; | |
| 1103 | return NULL; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) | ||
| 1107 | { | ||
| 1108 | static struct key_entry *key; | ||
| 1109 | |||
| 1110 | key = eeepc_get_entry_by_scancode(eeepc, event); | ||
| 1111 | if (key) { | ||
| 1112 | switch (key->type) { | ||
| 1113 | case KE_KEY: | ||
| 1114 | input_report_key(eeepc->inputdev, key->keycode, | ||
| 1115 | 1); | ||
| 1116 | input_sync(eeepc->inputdev); | ||
| 1117 | input_report_key(eeepc->inputdev, key->keycode, | ||
| 1118 | 0); | ||
| 1119 | input_sync(eeepc->inputdev); | ||
| 1120 | break; | ||
| 1121 | } | ||
| 1122 | } | 1154 | } | 
| 1123 | } | ||
| 1124 | |||
| 1125 | static struct key_entry *eeepc_get_entry_by_keycode( | ||
| 1126 | struct eeepc_laptop *eeepc, int code) | ||
| 1127 | { | ||
| 1128 | struct key_entry *key; | ||
| 1129 | |||
| 1130 | for (key = eeepc->keymap; key->type != KE_END; key++) | ||
| 1131 | if (code == key->keycode && key->type == KE_KEY) | ||
| 1132 | return key; | ||
| 1133 | 1155 | ||
| 1134 | return NULL; | 1156 | input->name = "Asus EeePC extra buttons"; | 
| 1135 | } | 1157 | input->phys = EEEPC_LAPTOP_FILE "/input0"; | 
| 1158 | input->id.bustype = BUS_HOST; | ||
| 1159 | input->dev.parent = &eeepc->platform_device->dev; | ||
| 1136 | 1160 | ||
| 1137 | static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) | 1161 | error = sparse_keymap_setup(input, eeepc_keymap, NULL); | 
| 1138 | { | 1162 | if (error) { | 
| 1139 | struct eeepc_laptop *eeepc = input_get_drvdata(dev); | 1163 | pr_err("Unable to setup input device keymap\n"); | 
| 1140 | struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); | 1164 | goto err_free_dev; | 
| 1141 | |||
| 1142 | if (key && key->type == KE_KEY) { | ||
| 1143 | *keycode = key->keycode; | ||
| 1144 | return 0; | ||
| 1145 | } | 1165 | } | 
| 1146 | 1166 | ||
| 1147 | return -EINVAL; | 1167 | error = input_register_device(input); | 
| 1148 | } | 1168 | if (error) { | 
| 1149 | 1169 | pr_err("Unable to register input device\n"); | |
| 1150 | static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | 1170 | goto err_free_keymap; | 
| 1151 | { | ||
| 1152 | struct eeepc_laptop *eeepc = input_get_drvdata(dev); | ||
| 1153 | struct key_entry *key; | ||
| 1154 | int old_keycode; | ||
| 1155 | |||
| 1156 | if (keycode < 0 || keycode > KEY_MAX) | ||
| 1157 | return -EINVAL; | ||
| 1158 | |||
| 1159 | key = eeepc_get_entry_by_scancode(eeepc, scancode); | ||
| 1160 | if (key && key->type == KE_KEY) { | ||
| 1161 | old_keycode = key->keycode; | ||
| 1162 | key->keycode = keycode; | ||
| 1163 | set_bit(keycode, dev->keybit); | ||
| 1164 | if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) | ||
| 1165 | clear_bit(old_keycode, dev->keybit); | ||
| 1166 | return 0; | ||
| 1167 | } | 1171 | } | 
| 1168 | 1172 | ||
| 1169 | return -EINVAL; | 1173 | eeepc->inputdev = input; | 
| 1170 | } | ||
| 1171 | |||
| 1172 | static int eeepc_input_init(struct eeepc_laptop *eeepc) | ||
| 1173 | { | ||
| 1174 | const struct key_entry *key; | ||
| 1175 | int result; | ||
| 1176 | |||
| 1177 | eeepc->inputdev = input_allocate_device(); | ||
| 1178 | if (!eeepc->inputdev) { | ||
| 1179 | pr_info("Unable to allocate input device\n"); | ||
| 1180 | return -ENOMEM; | ||
| 1181 | } | ||
| 1182 | eeepc->inputdev->name = "Asus EeePC extra buttons"; | ||
| 1183 | eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; | ||
| 1184 | eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; | ||
| 1185 | eeepc->inputdev->id.bustype = BUS_HOST; | ||
| 1186 | eeepc->inputdev->getkeycode = eeepc_getkeycode; | ||
| 1187 | eeepc->inputdev->setkeycode = eeepc_setkeycode; | ||
| 1188 | input_set_drvdata(eeepc->inputdev, eeepc); | ||
| 1189 | |||
| 1190 | eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), | ||
| 1191 | GFP_KERNEL); | ||
| 1192 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
| 1193 | switch (key->type) { | ||
| 1194 | case KE_KEY: | ||
| 1195 | set_bit(EV_KEY, eeepc->inputdev->evbit); | ||
| 1196 | set_bit(key->keycode, eeepc->inputdev->keybit); | ||
| 1197 | break; | ||
| 1198 | } | ||
| 1199 | } | ||
| 1200 | result = input_register_device(eeepc->inputdev); | ||
| 1201 | if (result) { | ||
| 1202 | pr_info("Unable to register input device\n"); | ||
| 1203 | input_free_device(eeepc->inputdev); | ||
| 1204 | return result; | ||
| 1205 | } | ||
| 1206 | return 0; | 1174 | return 0; | 
| 1175 | |||
| 1176 | err_free_keymap: | ||
| 1177 | sparse_keymap_free(input); | ||
| 1178 | err_free_dev: | ||
| 1179 | input_free_device(input); | ||
| 1180 | return error; | ||
| 1207 | } | 1181 | } | 
| 1208 | 1182 | ||
| 1209 | static void eeepc_input_exit(struct eeepc_laptop *eeepc) | 1183 | static void eeepc_input_exit(struct eeepc_laptop *eeepc) | 
| @@ -1253,11 +1227,59 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) | |||
| 1253 | * event will be desired value (or else ignored) | 1227 | * event will be desired value (or else ignored) | 
| 1254 | */ | 1228 | */ | 
| 1255 | } | 1229 | } | 
| 1256 | eeepc_input_notify(eeepc, event); | 1230 | sparse_keymap_report_event(eeepc->inputdev, event, | 
| 1231 | 1, true); | ||
| 1257 | } | 1232 | } | 
| 1258 | } else { | 1233 | } else { | 
| 1259 | /* Everything else is a bona-fide keypress event */ | 1234 | /* Everything else is a bona-fide keypress event */ | 
| 1260 | eeepc_input_notify(eeepc, event); | 1235 | sparse_keymap_report_event(eeepc->inputdev, event, 1, true); | 
| 1236 | } | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static void eeepc_dmi_check(struct eeepc_laptop *eeepc) | ||
| 1240 | { | ||
| 1241 | const char *model; | ||
| 1242 | |||
| 1243 | model = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
| 1244 | if (!model) | ||
| 1245 | return; | ||
| 1246 | |||
| 1247 | /* | ||
| 1248 | * Blacklist for setting cpufv (cpu speed). | ||
| 1249 | * | ||
| 1250 | * EeePC 4G ("701") implements CFVS, but it is not supported | ||
| 1251 | * by the pre-installed OS, and the original option to change it | ||
| 1252 | * in the BIOS setup screen was removed in later versions. | ||
| 1253 | * | ||
| 1254 | * Judging by the lack of "Super Hybrid Engine" on Asus product pages, | ||
| 1255 | * this applies to all "701" models (4G/4G Surf/2G Surf). | ||
| 1256 | * | ||
| 1257 | * So Asus made a deliberate decision not to support it on this model. | ||
| 1258 | * We have several reports that using it can cause the system to hang | ||
| 1259 | * | ||
| 1260 | * The hang has also been reported on a "702" (Model name "8G"?). | ||
| 1261 | * | ||
| 1262 | * We avoid dmi_check_system() / dmi_match(), because they use | ||
| 1263 | * substring matching. We don't want to affect the "701SD" | ||
| 1264 | * and "701SDX" models, because they do support S.H.E. | ||
| 1265 | */ | ||
| 1266 | if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { | ||
| 1267 | eeepc->cpufv_disabled = true; | ||
| 1268 | pr_info("model %s does not officially support setting cpu " | ||
| 1269 | "speed\n", model); | ||
| 1270 | pr_info("cpufv disabled to avoid instability\n"); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | /* | ||
| 1274 | * Blacklist for wlan hotplug | ||
| 1275 | * | ||
| 1276 | * Eeepc 1005HA doesn't work like others models and don't need the | ||
| 1277 | * hotplug code. In fact, current hotplug code seems to unplug another | ||
| 1278 | * device... | ||
| 1279 | */ | ||
| 1280 | if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { | ||
| 1281 | eeepc->hotplug_disabled = true; | ||
| 1282 | pr_info("wlan hotplug disabled\n"); | ||
| 1261 | } | 1283 | } | 
| 1262 | } | 1284 | } | 
| 1263 | 1285 | ||
| @@ -1342,6 +1364,10 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) | |||
| 1342 | strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); | 1364 | strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); | 
| 1343 | device->driver_data = eeepc; | 1365 | device->driver_data = eeepc; | 
| 1344 | 1366 | ||
| 1367 | eeepc->hotplug_disabled = hotplug_disabled; | ||
| 1368 | |||
| 1369 | eeepc_dmi_check(eeepc); | ||
| 1370 | |||
| 1345 | result = eeepc_acpi_init(eeepc, device); | 1371 | result = eeepc_acpi_init(eeepc, device); | 
| 1346 | if (result) | 1372 | if (result) | 
| 1347 | goto fail_platform; | 1373 | goto fail_platform; | 
| @@ -1452,10 +1478,12 @@ static int __init eeepc_laptop_init(void) | |||
| 1452 | result = acpi_bus_register_driver(&eeepc_acpi_driver); | 1478 | result = acpi_bus_register_driver(&eeepc_acpi_driver); | 
| 1453 | if (result < 0) | 1479 | if (result < 0) | 
| 1454 | goto fail_acpi_driver; | 1480 | goto fail_acpi_driver; | 
| 1481 | |||
| 1455 | if (!eeepc_device_present) { | 1482 | if (!eeepc_device_present) { | 
| 1456 | result = -ENODEV; | 1483 | result = -ENODEV; | 
| 1457 | goto fail_no_device; | 1484 | goto fail_no_device; | 
| 1458 | } | 1485 | } | 
| 1486 | |||
| 1459 | return 0; | 1487 | return 0; | 
| 1460 | 1488 | ||
| 1461 | fail_no_device: | 1489 | fail_no_device: | 
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6f..3f71a605a492 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c  | |||
| @@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) | |||
| 1201 | /* the buffer is filled with magic numbers describing the devices | 1201 | /* the buffer is filled with magic numbers describing the devices | 
| 1202 | * available, 0xff terminates the enumeration | 1202 | * available, 0xff terminates the enumeration | 
| 1203 | */ | 1203 | */ | 
| 1204 | while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && | 1204 | for (i = 0; i < device_enum->buffer.length; i++) { | 
| 1205 | i < device_enum->buffer.length) { | 1205 | |
| 1206 | i++; | 1206 | dev_code = *(device_enum->buffer.pointer + i); | 
| 1207 | if (dev_code == 0xff) | ||
| 1208 | break; | ||
| 1209 | |||
| 1207 | dprintk("Radio devices, looking at 0x%.2x\n", dev_code); | 1210 | dprintk("Radio devices, looking at 0x%.2x\n", dev_code); | 
| 1208 | 1211 | ||
| 1209 | if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) | 1212 | if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) | 
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 9d7febde10a1..09469971472f 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h  | |||
| @@ -152,7 +152,7 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) | |||
| 152 | #include <linux/hardirq.h> | 152 | #include <linux/hardirq.h> | 
| 153 | #define ACPI_PREEMPTION_POINT() \ | 153 | #define ACPI_PREEMPTION_POINT() \ | 
| 154 | do { \ | 154 | do { \ | 
| 155 | if (!in_atomic_preempt_off()) \ | 155 | if (!in_atomic_preempt_off() && !irqs_disabled()) \ | 
| 156 | cond_resched(); \ | 156 | cond_resched(); \ | 
| 157 | } while (0) | 157 | } while (0) | 
| 158 | 158 | ||
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 36924255c0d5..b926afe8c03e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h  | |||
| @@ -80,7 +80,7 @@ char * __acpi_map_table (unsigned long phys_addr, unsigned long size); | |||
| 80 | void __acpi_unmap_table(char *map, unsigned long size); | 80 | void __acpi_unmap_table(char *map, unsigned long size); | 
| 81 | int early_acpi_boot_init(void); | 81 | int early_acpi_boot_init(void); | 
| 82 | int acpi_boot_init (void); | 82 | int acpi_boot_init (void); | 
| 83 | int acpi_boot_table_init (void); | 83 | void acpi_boot_table_init (void); | 
| 84 | int acpi_mps_check (void); | 84 | int acpi_mps_check (void); | 
| 85 | int acpi_numa_init (void); | 85 | int acpi_numa_init (void); | 
| 86 | 86 | ||
| @@ -321,9 +321,9 @@ static inline int acpi_boot_init(void) | |||
| 321 | return 0; | 321 | return 0; | 
| 322 | } | 322 | } | 
| 323 | 323 | ||
| 324 | static inline int acpi_boot_table_init(void) | 324 | static inline void acpi_boot_table_init(void) | 
| 325 | { | 325 | { | 
| 326 | return 0; | 326 | return; | 
| 327 | } | 327 | } | 
| 328 | 328 | ||
| 329 | static inline int acpi_mps_check(void) | 329 | static inline int acpi_mps_check(void) | 
