diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-11 11:35:05 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-11 11:35:05 -0500 |
| commit | 37d11391c2de8a846da50a2972a82289e65e5ea6 (patch) | |
| tree | 9ada78f04f57cb1deadc8cc30a1efe55c396cbf0 | |
| parent | e06bf91b59d3d95359e046ffcdc577145933da10 (diff) | |
Revert "ACPI / EC: Add query flushing support"
Revert commit f252cb09e1cb (ACPI / EC: Add query flushing support),
because it breaks system suspend on Acer Aspire S5. The machine
just hangs solid at the last stage of suspend (after taking non-boot
CPUs offline).
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
| -rw-r--r-- | drivers/acpi/ec.c | 101 |
1 files changed, 16 insertions, 85 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 40002ae7db2b..982b67faaaf3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -76,9 +76,7 @@ enum ec_command { | |||
| 76 | * when trying to clear the EC */ | 76 | * when trying to clear the EC */ |
| 77 | 77 | ||
| 78 | enum { | 78 | enum { |
| 79 | EC_FLAGS_EVENT_ENABLED, /* Event is enabled */ | 79 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
| 80 | EC_FLAGS_EVENT_PENDING, /* Event is pending */ | ||
| 81 | EC_FLAGS_EVENT_DETECTED, /* Event is detected */ | ||
| 82 | EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and | 80 | EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and |
| 83 | * OpReg are installed */ | 81 | * OpReg are installed */ |
| 84 | EC_FLAGS_STARTED, /* Driver is started */ | 82 | EC_FLAGS_STARTED, /* Driver is started */ |
| @@ -153,12 +151,6 @@ static bool acpi_ec_flushed(struct acpi_ec *ec) | |||
| 153 | return ec->reference_count == 1; | 151 | return ec->reference_count == 1; |
| 154 | } | 152 | } |
| 155 | 153 | ||
| 156 | static bool acpi_ec_has_pending_event(struct acpi_ec *ec) | ||
| 157 | { | ||
| 158 | return test_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags) || | ||
| 159 | test_bit(EC_FLAGS_EVENT_PENDING, &ec->flags); | ||
| 160 | } | ||
| 161 | |||
| 162 | /* -------------------------------------------------------------------------- | 154 | /* -------------------------------------------------------------------------- |
| 163 | * EC Registers | 155 | * EC Registers |
| 164 | * -------------------------------------------------------------------------- */ | 156 | * -------------------------------------------------------------------------- */ |
| @@ -326,93 +318,36 @@ static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag) | |||
| 326 | * the flush operation is not in | 318 | * the flush operation is not in |
| 327 | * progress | 319 | * progress |
| 328 | * @ec: the EC device | 320 | * @ec: the EC device |
| 329 | * @allow_event: whether event should be handled | ||
| 330 | * | 321 | * |
| 331 | * This function must be used before taking a new action that should hold | 322 | * This function must be used before taking a new action that should hold |
| 332 | * the reference count. If this function returns false, then the action | 323 | * the reference count. If this function returns false, then the action |
| 333 | * must be discarded or it will prevent the flush operation from being | 324 | * must be discarded or it will prevent the flush operation from being |
| 334 | * completed. | 325 | * completed. |
| 335 | * | ||
| 336 | * During flushing, QR_EC command need to pass this check when there is a | ||
| 337 | * pending event, so that the reference count held for the pending event | ||
| 338 | * can be decreased by the completion of the QR_EC command. | ||
| 339 | */ | 326 | */ |
| 340 | static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec, | 327 | static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec) |
| 341 | bool allow_event) | ||
| 342 | { | 328 | { |
| 343 | if (!acpi_ec_started(ec)) { | 329 | if (!acpi_ec_started(ec)) |
| 344 | if (!allow_event || !acpi_ec_has_pending_event(ec)) | 330 | return false; |
| 345 | return false; | ||
| 346 | } | ||
| 347 | acpi_ec_submit_request(ec); | 331 | acpi_ec_submit_request(ec); |
| 348 | return true; | 332 | return true; |
| 349 | } | 333 | } |
| 350 | 334 | ||
| 351 | static void acpi_ec_submit_event(struct acpi_ec *ec) | 335 | static void acpi_ec_submit_query(struct acpi_ec *ec) |
| 352 | { | 336 | { |
| 353 | if (!test_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags) || | 337 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { |
| 354 | !test_bit(EC_FLAGS_EVENT_ENABLED, &ec->flags)) | 338 | pr_debug("***** Event started *****\n"); |
| 355 | return; | ||
| 356 | /* Hold reference for pending event */ | ||
| 357 | if (!acpi_ec_submit_flushable_request(ec, true)) | ||
| 358 | return; | ||
| 359 | if (!test_and_set_bit(EC_FLAGS_EVENT_PENDING, &ec->flags)) { | ||
| 360 | pr_debug("***** Event query started *****\n"); | ||
| 361 | schedule_work(&ec->work); | 339 | schedule_work(&ec->work); |
| 362 | return; | ||
| 363 | } | ||
| 364 | acpi_ec_complete_request(ec); | ||
| 365 | } | ||
| 366 | |||
| 367 | static void acpi_ec_complete_event(struct acpi_ec *ec) | ||
| 368 | { | ||
| 369 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | ||
| 370 | clear_bit(EC_FLAGS_EVENT_PENDING, &ec->flags); | ||
| 371 | pr_debug("***** Event query stopped *****\n"); | ||
| 372 | /* Unhold reference for pending event */ | ||
| 373 | acpi_ec_complete_request(ec); | ||
| 374 | /* Check if there is another SCI_EVT detected */ | ||
| 375 | acpi_ec_submit_event(ec); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | static void acpi_ec_submit_detection(struct acpi_ec *ec) | ||
| 380 | { | ||
| 381 | /* Hold reference for query submission */ | ||
| 382 | if (!acpi_ec_submit_flushable_request(ec, false)) | ||
| 383 | return; | ||
| 384 | if (!test_and_set_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags)) { | ||
| 385 | pr_debug("***** Event detection blocked *****\n"); | ||
| 386 | acpi_ec_submit_event(ec); | ||
| 387 | return; | ||
| 388 | } | 340 | } |
| 389 | acpi_ec_complete_request(ec); | ||
| 390 | } | 341 | } |
| 391 | 342 | ||
| 392 | static void acpi_ec_complete_detection(struct acpi_ec *ec) | 343 | static void acpi_ec_complete_query(struct acpi_ec *ec) |
| 393 | { | 344 | { |
| 394 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | 345 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { |
| 395 | clear_bit(EC_FLAGS_EVENT_DETECTED, &ec->flags); | 346 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
| 396 | pr_debug("***** Event detetion unblocked *****\n"); | 347 | pr_debug("***** Event stopped *****\n"); |
| 397 | /* Unhold reference for query submission */ | ||
| 398 | acpi_ec_complete_request(ec); | ||
| 399 | } | 348 | } |
| 400 | } | 349 | } |
| 401 | 350 | ||
| 402 | static void acpi_ec_enable_event(struct acpi_ec *ec) | ||
| 403 | { | ||
| 404 | unsigned long flags; | ||
| 405 | |||
| 406 | spin_lock_irqsave(&ec->lock, flags); | ||
| 407 | set_bit(EC_FLAGS_EVENT_ENABLED, &ec->flags); | ||
| 408 | /* | ||
| 409 | * An event may be pending even with SCI_EVT=0, so QR_EC should | ||
| 410 | * always be issued right after started. | ||
| 411 | */ | ||
| 412 | acpi_ec_submit_detection(ec); | ||
| 413 | spin_unlock_irqrestore(&ec->lock, flags); | ||
| 414 | } | ||
| 415 | |||
| 416 | static int ec_transaction_completed(struct acpi_ec *ec) | 351 | static int ec_transaction_completed(struct acpi_ec *ec) |
| 417 | { | 352 | { |
| 418 | unsigned long flags; | 353 | unsigned long flags; |
| @@ -454,7 +389,6 @@ static void advance_transaction(struct acpi_ec *ec) | |||
| 454 | t->rdata[t->ri++] = acpi_ec_read_data(ec); | 389 | t->rdata[t->ri++] = acpi_ec_read_data(ec); |
| 455 | if (t->rlen == t->ri) { | 390 | if (t->rlen == t->ri) { |
| 456 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | 391 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
| 457 | acpi_ec_complete_event(ec); | ||
| 458 | if (t->command == ACPI_EC_COMMAND_QUERY) | 392 | if (t->command == ACPI_EC_COMMAND_QUERY) |
| 459 | pr_debug("***** Command(%s) hardware completion *****\n", | 393 | pr_debug("***** Command(%s) hardware completion *****\n", |
| 460 | acpi_ec_cmd_string(t->command)); | 394 | acpi_ec_cmd_string(t->command)); |
| @@ -465,7 +399,6 @@ static void advance_transaction(struct acpi_ec *ec) | |||
| 465 | } else if (t->wlen == t->wi && | 399 | } else if (t->wlen == t->wi && |
| 466 | (status & ACPI_EC_FLAG_IBF) == 0) { | 400 | (status & ACPI_EC_FLAG_IBF) == 0) { |
| 467 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | 401 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
| 468 | acpi_ec_complete_event(ec); | ||
| 469 | wakeup = true; | 402 | wakeup = true; |
| 470 | } | 403 | } |
| 471 | goto out; | 404 | goto out; |
| @@ -474,17 +407,16 @@ static void advance_transaction(struct acpi_ec *ec) | |||
| 474 | !(status & ACPI_EC_FLAG_SCI) && | 407 | !(status & ACPI_EC_FLAG_SCI) && |
| 475 | (t->command == ACPI_EC_COMMAND_QUERY)) { | 408 | (t->command == ACPI_EC_COMMAND_QUERY)) { |
| 476 | t->flags |= ACPI_EC_COMMAND_POLL; | 409 | t->flags |= ACPI_EC_COMMAND_POLL; |
| 477 | acpi_ec_complete_detection(ec); | 410 | acpi_ec_complete_query(ec); |
| 478 | t->rdata[t->ri++] = 0x00; | 411 | t->rdata[t->ri++] = 0x00; |
| 479 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | 412 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
| 480 | acpi_ec_complete_event(ec); | ||
| 481 | pr_debug("***** Command(%s) software completion *****\n", | 413 | pr_debug("***** Command(%s) software completion *****\n", |
| 482 | acpi_ec_cmd_string(t->command)); | 414 | acpi_ec_cmd_string(t->command)); |
| 483 | wakeup = true; | 415 | wakeup = true; |
| 484 | } else if ((status & ACPI_EC_FLAG_IBF) == 0) { | 416 | } else if ((status & ACPI_EC_FLAG_IBF) == 0) { |
| 485 | acpi_ec_write_cmd(ec, t->command); | 417 | acpi_ec_write_cmd(ec, t->command); |
| 486 | t->flags |= ACPI_EC_COMMAND_POLL; | 418 | t->flags |= ACPI_EC_COMMAND_POLL; |
| 487 | acpi_ec_complete_detection(ec); | 419 | acpi_ec_complete_query(ec); |
| 488 | } else | 420 | } else |
| 489 | goto err; | 421 | goto err; |
| 490 | goto out; | 422 | goto out; |
| @@ -505,7 +437,7 @@ err: | |||
| 505 | } | 437 | } |
| 506 | out: | 438 | out: |
| 507 | if (status & ACPI_EC_FLAG_SCI) | 439 | if (status & ACPI_EC_FLAG_SCI) |
| 508 | acpi_ec_submit_detection(ec); | 440 | acpi_ec_submit_query(ec); |
| 509 | if (wakeup && in_interrupt()) | 441 | if (wakeup && in_interrupt()) |
| 510 | wake_up(&ec->wait); | 442 | wake_up(&ec->wait); |
| 511 | } | 443 | } |
| @@ -566,7 +498,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 566 | /* start transaction */ | 498 | /* start transaction */ |
| 567 | spin_lock_irqsave(&ec->lock, tmp); | 499 | spin_lock_irqsave(&ec->lock, tmp); |
| 568 | /* Enable GPE for command processing (IBF=0/OBF=1) */ | 500 | /* Enable GPE for command processing (IBF=0/OBF=1) */ |
| 569 | if (!acpi_ec_submit_flushable_request(ec, true)) { | 501 | if (!acpi_ec_submit_flushable_request(ec)) { |
