diff options
| author | H. Peter Anvin <hpa@zytor.com> | 2010-02-22 19:20:34 -0500 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-22 19:20:34 -0500 |
| commit | d02e30c31c57683a66ed68a1bcff900ca78f6d56 (patch) | |
| tree | c3ce99a00061bcc1199b50fa838147d876c56717 /drivers/acpi | |
| parent | 0fdc7a8022c3eaff6b5ee27ffb9e913e5e58d8e9 (diff) | |
| parent | aef55d4922e62a0d887e60d87319f3718aec6ced (diff) | |
Merge branch 'x86/irq' into x86/apic
Merge reason:
Conflicts in arch/x86/kernel/apic/io_apic.c
Resolved Conflicts:
arch/x86/kernel/apic/io_apic.c
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'drivers/acpi')
| -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/numa.c | 4 | ||||
| -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/sleep.c | 29 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 51 |
15 files changed, 242 insertions, 126 deletions
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/numa.c b/drivers/acpi/numa.c index 7ad48dfc12db..b8725461d887 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
| @@ -279,9 +279,9 @@ int __init acpi_numa_init(void) | |||
| 279 | /* SRAT: Static Resource Affinity Table */ | 279 | /* SRAT: Static Resource Affinity Table */ |
| 280 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { | 280 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { |
| 281 | acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, | 281 | acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, |
| 282 | acpi_parse_x2apic_affinity, NR_CPUS); | 282 | acpi_parse_x2apic_affinity, nr_cpu_ids); |
| 283 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, | 283 | acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, |
| 284 | acpi_parse_processor_affinity, NR_CPUS); | 284 | acpi_parse_processor_affinity, nr_cpu_ids); |
| 285 | ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, | 285 | ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, |
| 286 | acpi_parse_memory_affinity, | 286 | acpi_parse_memory_affinity, |
| 287 | NR_NODE_MEMBLKS); | 287 | NR_NODE_MEMBLKS); |
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/sleep.c b/drivers/acpi/sleep.c index 5f2c379ab7bf..79d33d908b5a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -81,6 +81,23 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
| 81 | #ifdef CONFIG_ACPI_SLEEP | 81 | #ifdef CONFIG_ACPI_SLEEP |
| 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
| 83 | /* | 83 | /* |
| 84 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
| 85 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
| 86 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
| 87 | * on such systems during resume. Unfortunately that doesn't help in | ||
| 88 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
| 89 | * resume, although the specification states very clearly that this flag is | ||
| 90 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
| 91 | * cases. | ||
| 92 | */ | ||
| 93 | static bool set_sci_en_on_resume; | ||
| 94 | |||
| 95 | void __init acpi_set_sci_en_on_resume(void) | ||
| 96 | { | ||
| 97 | set_sci_en_on_resume = true; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 84 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 101 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
| 85 | * user to request that behavior by using the 'acpi_old_suspend_ordering' | 102 | * user to request that behavior by using the 'acpi_old_suspend_ordering' |
| 86 | * kernel command line option that causes the following variable to be set. | 103 | * kernel command line option that causes the following variable to be set. |
| @@ -170,18 +187,6 @@ static void acpi_pm_end(void) | |||
| 170 | #endif /* CONFIG_ACPI_SLEEP */ | 187 | #endif /* CONFIG_ACPI_SLEEP */ |
| 171 | 188 | ||
| 172 | #ifdef CONFIG_SUSPEND | 189 | #ifdef CONFIG_SUSPEND |
| 173 | /* | ||
| 174 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
| 175 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
| 176 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
| 177 | * on such systems during resume. Unfortunately that doesn't help in | ||
| 178 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
| 179 | * resume, although the specification states very clearly that this flag is | ||
| 180 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
| 181 | * cases. | ||
| 182 | */ | ||
| 183 | static bool set_sci_en_on_resume; | ||
| 184 | |||
| 185 | extern void do_suspend_lowlevel(void); | 190 | extern void do_suspend_lowlevel(void); |
| 186 | 191 | ||
| 187 | static u32 acpi_suspend_states[] = { | 192 | static u32 acpi_suspend_states[] = { |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591c..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); |
| @@ -999,8 +1006,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 999 | sprintf(name, "acpi_video%d", count++); | 1006 | sprintf(name, "acpi_video%d", count++); |
| 1000 | device->backlight = backlight_device_register(name, | 1007 | device->backlight = backlight_device_register(name, |
| 1001 | NULL, device, &acpi_backlight_ops); | 1008 | NULL, device, &acpi_backlight_ops); |
| 1002 | device->backlight->props.max_brightness = device->brightness->count-3; | ||
| 1003 | kfree(name); | 1009 | kfree(name); |
| 1010 | if (IS_ERR(device->backlight)) | ||
| 1011 | return; | ||
| 1012 | device->backlight->props.max_brightness = device->brightness->count-3; | ||
| 1004 | 1013 | ||
| 1005 | result = sysfs_create_link(&device->backlight->dev.kobj, | 1014 | result = sysfs_create_link(&device->backlight->dev.kobj, |
| 1006 | &device->dev->dev.kobj, "device"); | 1015 | &device->dev->dev.kobj, "device"); |
| @@ -1979,6 +1988,10 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) | |||
| 1979 | unsigned long long level_current, level_next; | 1988 | unsigned long long level_current, level_next; |
| 1980 | int result = -EINVAL; | 1989 | int result = -EINVAL; |
| 1981 | 1990 | ||
| 1991 | /* no warning message if acpi_backlight=vendor is used */ | ||
| 1992 | if (!acpi_video_backlight_support()) | ||
| 1993 | return 0; | ||
| 1994 | |||
| 1982 | if (!device->brightness) | 1995 | if (!device->brightness) |
| 1983 | goto out; | 1996 | goto out; |
| 1984 | 1997 | ||
| @@ -2233,11 +2246,47 @@ static int acpi_video_resume(struct acpi_device *device) | |||
| 2233 | return AE_OK; | 2246 | return AE_OK; |
| 2234 | } | 2247 | } |
| 2235 | 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 | |||
| 2236 | static int acpi_video_bus_add(struct acpi_device *device) | 2270 | static int acpi_video_bus_add(struct acpi_device *device) |
| 2237 | { | 2271 | { |
| 2238 | struct acpi_video_bus *video; | 2272 | struct acpi_video_bus *video; |
| 2239 | struct input_dev *input; | 2273 | struct input_dev *input; |
| 2240 | 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 | } | ||
| 2241 | 2290 | ||
| 2242 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 2291 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); |
| 2243 | if (!video) | 2292 | if (!video) |
