aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/coupled.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c
index 5d3962730063..f8a86364c6b6 100644
--- a/drivers/cpuidle/coupled.c
+++ b/drivers/cpuidle/coupled.c
@@ -408,19 +408,22 @@ static void cpuidle_coupled_set_done(int cpu, struct cpuidle_coupled *coupled)
408 * been processed and the poke bit has been cleared. 408 * been processed and the poke bit has been cleared.
409 * 409 *
410 * Other interrupts may also be processed while interrupts are enabled, so 410 * Other interrupts may also be processed while interrupts are enabled, so
411 * need_resched() must be tested after turning interrupts off again to make sure 411 * need_resched() must be tested after this function returns to make sure
412 * the interrupt didn't schedule work that should take the cpu out of idle. 412 * the interrupt didn't schedule work that should take the cpu out of idle.
413 * 413 *
414 * Returns 0 if need_resched was false, -EINTR if need_resched was true. 414 * Returns 0 if no poke was pending, 1 if a poke was cleared.
415 */ 415 */
416static int cpuidle_coupled_clear_pokes(int cpu) 416static int cpuidle_coupled_clear_pokes(int cpu)
417{ 417{
418 if (!cpumask_test_cpu(cpu, &cpuidle_coupled_poke_pending))
419 return 0;
420
418 local_irq_enable(); 421 local_irq_enable();
419 while (cpumask_test_cpu(cpu, &cpuidle_coupled_poke_pending)) 422 while (cpumask_test_cpu(cpu, &cpuidle_coupled_poke_pending))
420 cpu_relax(); 423 cpu_relax();
421 local_irq_disable(); 424 local_irq_disable();
422 425
423 return need_resched() ? -EINTR : 0; 426 return 1;
424} 427}
425 428
426static bool cpuidle_coupled_any_pokes_pending(struct cpuidle_coupled *coupled) 429static bool cpuidle_coupled_any_pokes_pending(struct cpuidle_coupled *coupled)
@@ -464,7 +467,8 @@ int cpuidle_enter_state_coupled(struct cpuidle_device *dev,
464 return -EINVAL; 467 return -EINVAL;
465 468
466 while (coupled->prevent) { 469 while (coupled->prevent) {
467 if (cpuidle_coupled_clear_pokes(dev->cpu)) { 470 cpuidle_coupled_clear_pokes(dev->cpu);
471 if (need_resched()) {
468 local_irq_enable(); 472 local_irq_enable();
469 return entered_state; 473 return entered_state;
470 } 474 }
@@ -503,7 +507,10 @@ retry:
503 */ 507 */
504 while (!cpuidle_coupled_cpus_waiting(coupled) || 508 while (!cpuidle_coupled_cpus_waiting(coupled) ||
505 !cpumask_test_cpu(dev->cpu, &cpuidle_coupled_poked)) { 509 !cpumask_test_cpu(dev->cpu, &cpuidle_coupled_poked)) {
506 if (cpuidle_coupled_clear_pokes(dev->cpu)) { 510 if (cpuidle_coupled_clear_pokes(dev->cpu))
511 continue;
512
513 if (need_resched()) {
507 cpuidle_coupled_set_not_waiting(dev->cpu, coupled); 514 cpuidle_coupled_set_not_waiting(dev->cpu, coupled);
508 goto out; 515 goto out;
509 } 516 }
@@ -518,7 +525,8 @@ retry:
518 local_irq_disable(); 525 local_irq_disable();
519 } 526 }
520 527
521 if (cpuidle_coupled_clear_pokes(dev->cpu)) { 528 cpuidle_coupled_clear_pokes(dev->cpu);
529 if (need_resched()) {
522 cpuidle_coupled_set_not_waiting(dev->cpu, coupled); 530 cpuidle_coupled_set_not_waiting(dev->cpu, coupled);
523 goto out; 531 goto out;
524 } 532 }