aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2013-09-11 06:43:13 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-29 14:11:42 -0500
commite895dad0a5b1db5475346d9c2ae4a92e6fefa58d (patch)
tree5a1333b355a74c688a911fb2926c127236b55cef /drivers/acpi
parent5bad04d7bc7fe12a89b716f8b63d32b5735f6dd2 (diff)
sched, idle: Fix the idle polling state logic
commit ea8117478918a4734586d35ff530721b682425be upstream. Mike reported that commit 7d1a9417 ("x86: Use generic idle loop") regressed several workloads and caused excessive reschedule interrupts. The patch in question failed to notice that the x86 code had an inverted sense of the polling state versus the new generic code (x86: default polling, generic: default !polling). Fix the two prominent x86 mwait based idle drivers and introduce a few new generic polling helpers (fixing the wrong smp_mb__after_clear_bit usage). Also switch the idle routines to using tif_need_resched() which is an immediate TIF_NEED_RESCHED test as opposed to need_resched which will end up being slightly different. Reported-by: Mike Galbraith <bitbucket@online.de> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: lenb@kernel.org Cc: tglx@linutronix.de Link: http://lkml.kernel.org/n/tip-nc03imb0etuefmzybzj7sprf@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/processor_idle.c46
1 files changed, 10 insertions, 36 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index eb133c77aadb..4056d3175178 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -121,17 +121,10 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
121 */ 121 */
122static void acpi_safe_halt(void) 122static void acpi_safe_halt(void)
123{ 123{
124 current_thread_info()->status &= ~TS_POLLING; 124 if (!tif_need_resched()) {
125 /*
126 * TS_POLLING-cleared state must be visible before we
127 * test NEED_RESCHED:
128 */
129 smp_mb();
130 if (!need_resched()) {
131 safe_halt(); 125 safe_halt();
132 local_irq_disable(); 126 local_irq_disable();
133 } 127 }
134 current_thread_info()->status |= TS_POLLING;
135} 128}
136 129
137#ifdef ARCH_APICTIMER_STOPS_ON_C3 130#ifdef ARCH_APICTIMER_STOPS_ON_C3
@@ -739,6 +732,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
739 if (unlikely(!pr)) 732 if (unlikely(!pr))
740 return -EINVAL; 733 return -EINVAL;
741 734
735 if (cx->entry_method == ACPI_CSTATE_FFH) {
736 if (current_set_polling_and_test())
737 return -EINVAL;
738 }
739
742 lapic_timer_state_broadcast(pr, cx, 1); 740 lapic_timer_state_broadcast(pr, cx, 1);
743 acpi_idle_do_entry(cx); 741 acpi_idle_do_entry(cx);
744 742
@@ -792,18 +790,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
792 if (unlikely(!pr)) 790 if (unlikely(!pr))
793 return -EINVAL; 791 return -EINVAL;
794 792
795 if (cx->entry_method != ACPI_CSTATE_FFH) { 793 if (cx->entry_method == ACPI_CSTATE_FFH) {
796 current_thread_info()->status &= ~TS_POLLING; 794 if (current_set_polling_and_test())
797 /*
798 * TS_POLLING-cleared state must be visible before we test
799 * NEED_RESCHED:
800 */
801 smp_mb();
802
803 if (unlikely(need_resched())) {
804 current_thread_info()->status |= TS_POLLING;
805 return -EINVAL; 795 return -EINVAL;
806 }
807 } 796 }
808 797
809 /* 798 /*
@@ -821,9 +810,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
821 810
822 sched_clock_idle_wakeup_event(0); 811 sched_clock_idle_wakeup_event(0);
823 812
824 if (cx->entry_method != ACPI_CSTATE_FFH)
825 current_thread_info()->status |= TS_POLLING;
826
827 lapic_timer_state_broadcast(pr, cx, 0); 813 lapic_timer_state_broadcast(pr, cx, 0);
828 return index; 814 return index;
829} 815}
@@ -860,18 +846,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
860 } 846 }
861 } 847 }
862 848
863 if (cx->entry_method != ACPI_CSTATE_FFH) { 849 if (cx->entry_method == ACPI_CSTATE_FFH) {
864 current_thread_info()->status &= ~TS_POLLING; 850 if (current_set_polling_and_test())
865 /*
866 * TS_POLLING-cleared state must be visible before we test
867 * NEED_RESCHED:
868 */
869 smp_mb();
870
871 if (unlikely(need_resched())) {
872 current_thread_info()->status |= TS_POLLING;
873 return -EINVAL; 851 return -EINVAL;
874 }
875 } 852 }
876 853
877 acpi_unlazy_tlb(smp_processor_id()); 854 acpi_unlazy_tlb(smp_processor_id());
@@ -917,9 +894,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
917 894
918 sched_clock_idle_wakeup_event(0); 895 sched_clock_idle_wakeup_event(0);
919 896
920 if (cx->entry_method != ACPI_CSTATE_FFH)
921 current_thread_info()->status |= TS_POLLING;
922
923 lapic_timer_state_broadcast(pr, cx, 0); 897 lapic_timer_state_broadcast(pr, cx, 0);
924 return index; 898 return index;
925} 899}