aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_idle.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-05 01:39:07 -0400
committerLen Brown <len.brown@intel.com>2009-04-05 01:39:07 -0400
commit2ddb9f17ba026122b53b34fb4182ece91e24cf92 (patch)
tree5338e99d3bf91b02fbf12bfcc90538e253617eee /drivers/acpi/processor_idle.c
parenta3b2c5e413ce500d19cb776662ae0ea405cdd994 (diff)
parentff69f2bba67bd45514923aaedbf40fe351787c59 (diff)
Merge branch 'pmtimer-overflow' into release
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r--drivers/acpi/processor_idle.c63
1 files changed, 27 insertions, 36 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 397f2a7fee48..4e6e758bd397 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -64,7 +64,6 @@
64#define _COMPONENT ACPI_PROCESSOR_COMPONENT 64#define _COMPONENT ACPI_PROCESSOR_COMPONENT
65ACPI_MODULE_NAME("processor_idle"); 65ACPI_MODULE_NAME("processor_idle");
66#define ACPI_PROCESSOR_FILE_POWER "power" 66#define ACPI_PROCESSOR_FILE_POWER "power"
67#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
68#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) 67#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
69#define C2_OVERHEAD 1 /* 1us */ 68#define C2_OVERHEAD 1 /* 1us */
70#define C3_OVERHEAD 1 /* 1us */ 69#define C3_OVERHEAD 1 /* 1us */
@@ -78,6 +77,10 @@ module_param(nocst, uint, 0000);
78static unsigned int latency_factor __read_mostly = 2; 77static unsigned int latency_factor __read_mostly = 2;
79module_param(latency_factor, uint, 0644); 78module_param(latency_factor, uint, 0644);
80 79
80static s64 us_to_pm_timer_ticks(s64 t)
81{
82 return div64_u64(t * PM_TIMER_FREQUENCY, 1000000);
83}
81/* 84/*
82 * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. 85 * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
83 * For now disable this. Probably a bug somewhere else. 86 * For now disable this. Probably a bug somewhere else.
@@ -108,25 +111,6 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
108 {}, 111 {},
109}; 112};
110 113
111static inline u32 ticks_elapsed(u32 t1, u32 t2)
112{
113 if (t2 >= t1)
114 return (t2 - t1);
115 else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
116 return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
117 else
118 return ((0xFFFFFFFF - t1) + t2);
119}
120
121static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
122{
123 if (t2 >= t1)
124 return PM_TIMER_TICKS_TO_US(t2 - t1);
125 else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER))
126 return PM_TIMER_TICKS_TO_US(((0x00FFFFFF - t1) + t2) & 0x00FFFFFF);
127 else
128 return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
129}
130 114
131/* 115/*
132 * Callers should disable interrupts before the call and enable 116 * Callers should disable interrupts before the call and enable
@@ -802,7 +786,8 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
802static int acpi_idle_enter_c1(struct cpuidle_device *dev, 786static int acpi_idle_enter_c1(struct cpuidle_device *dev,
803 struct cpuidle_state *state) 787 struct cpuidle_state *state)
804{ 788{
805 u32 t1, t2; 789 ktime_t kt1, kt2;
790 s64 idle_time;
806 struct acpi_processor *pr; 791 struct acpi_processor *pr;
807 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 792 struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
808 793
@@ -820,14 +805,15 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
820 return 0; 805 return 0;
821 } 806 }
822 807
823 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); 808 kt1 = ktime_get_real();
824 acpi_idle_do_entry(cx); 809 acpi_idle_do_entry(cx);
825 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 810 kt2 = ktime_get_real();
811 idle_time = ktime_to_us(ktime_sub(kt2, kt1));
826 812
827 local_irq_enable(); 813 local_irq_enable();
828 cx->usage++; 814 cx->usage++;
829 815
830 return ticks_elapsed_in_us(t1, t2); 816 return idle_time;
831} 817}
832 818
833/** 819/**
@@ -840,8 +826,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
840{ 826{
841 struct acpi_processor *pr; 827 struct acpi_processor *pr;
842 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 828 struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
843 u32 t1, t2; 829 ktime_t kt1, kt2;
844 int sleep_ticks = 0; 830 s64 idle_time;
831 s64 sleep_ticks = 0;
845 832
846 pr = __get_cpu_var(processors); 833 pr = __get_cpu_var(processors);
847 834
@@ -874,18 +861,19 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
874 if (cx->type == ACPI_STATE_C3) 861 if (cx->type == ACPI_STATE_C3)
875 ACPI_FLUSH_CPU_CACHE(); 862 ACPI_FLUSH_CPU_CACHE();
876 863
877 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); 864 kt1 = ktime_get_real();
878 /* Tell the scheduler that we are going deep-idle: */ 865 /* Tell the scheduler that we are going deep-idle: */
879 sched_clock_idle_sleep_event(); 866 sched_clock_idle_sleep_event();
880 acpi_idle_do_entry(cx); 867 acpi_idle_do_entry(cx);
881 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 868 kt2 = ktime_get_real();
869 idle_time = ktime_to_us(ktime_sub(kt2, kt1));
882 870
883#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) 871#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
884 /* TSC could halt in idle, so notify users */ 872 /* TSC could halt in idle, so notify users */
885 if (tsc_halts_in_c(cx->type)) 873 if (tsc_halts_in_c(cx->type))
886 mark_tsc_unstable("TSC halts in idle");; 874 mark_tsc_unstable("TSC halts in idle");;
887#endif 875#endif
888 sleep_ticks = ticks_elapsed(t1, t2); 876 sleep_ticks = us_to_pm_timer_ticks(idle_time);
889 877
890 /* Tell the scheduler how much we idled: */ 878 /* Tell the scheduler how much we idled: */
891 sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); 879 sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
@@ -897,7 +885,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
897 885
898 acpi_state_timer_broadcast(pr, cx, 0); 886 acpi_state_timer_broadcast(pr, cx, 0);
899 cx->time += sleep_ticks; 887 cx->time += sleep_ticks;
900 return ticks_elapsed_in_us(t1, t2); 888 return idle_time;
901} 889}
902 890
903static int c3_cpu_count; 891static int c3_cpu_count;
@@ -915,8 +903,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
915{ 903{
916 struct acpi_processor *pr; 904 struct acpi_processor *pr;
917 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 905 struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
918 u32 t1, t2; 906 ktime_t kt1, kt2;
919 int sleep_ticks = 0; 907 s64 idle_time;
908 s64 sleep_ticks = 0;
909
920 910
921 pr = __get_cpu_var(processors); 911 pr = __get_cpu_var(processors);
922 912
@@ -983,9 +973,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
983 ACPI_FLUSH_CPU_CACHE(); 973 ACPI_FLUSH_CPU_CACHE();
984 } 974 }
985 975
986 t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); 976 kt1 = ktime_get_real();
987 acpi_idle_do_entry(cx); 977 acpi_idle_do_entry(cx);
988 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 978 kt2 = ktime_get_real();
979 idle_time = ktime_to_us(ktime_sub(kt2, kt1));
989 980
990 /* Re-enable bus master arbitration */ 981 /* Re-enable bus master arbitration */
991 if (pr->flags.bm_check && pr->flags.bm_control) { 982 if (pr->flags.bm_check && pr->flags.bm_control) {
@@ -1000,7 +991,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
1000 if (tsc_halts_in_c(ACPI_STATE_C3)) 991 if (tsc_halts_in_c(ACPI_STATE_C3))
1001 mark_tsc_unstable("TSC halts in idle"); 992 mark_tsc_unstable("TSC halts in idle");
1002#endif 993#endif
1003 sleep_ticks = ticks_elapsed(t1, t2); 994 sleep_ticks = us_to_pm_timer_ticks(idle_time);
1004 /* Tell the scheduler how much we idled: */ 995 /* Tell the scheduler how much we idled: */
1005 sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); 996 sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
1006 997
@@ -1011,7 +1002,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
1011 1002
1012 acpi_state_timer_broadcast(pr, cx, 0); 1003 acpi_state_timer_broadcast(pr, cx, 0);
1013 cx->time += sleep_ticks; 1004 cx->time += sleep_ticks;
1014 return ticks_elapsed_in_us(t1, t2); 1005 return idle_time;
1015} 1006}
1016 1007
1017struct cpuidle_driver acpi_idle_driver = { 1008struct cpuidle_driver acpi_idle_driver = {