diff options
-rw-r--r-- | drivers/acpi/processor_idle.c | 63 |
1 files changed, 27 insertions, 36 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7bc22a471fe3..879af875c213 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 |
65 | ACPI_MODULE_NAME("processor_idle"); | 65 | ACPI_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); | |||
78 | static unsigned int latency_factor __read_mostly = 2; | 77 | static unsigned int latency_factor __read_mostly = 2; |
79 | module_param(latency_factor, uint, 0644); | 78 | module_param(latency_factor, uint, 0644); |
80 | 79 | ||
80 | static 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. |
@@ -159,25 +162,6 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { | |||
159 | {}, | 162 | {}, |
160 | }; | 163 | }; |
161 | 164 | ||
162 | static inline u32 ticks_elapsed(u32 t1, u32 t2) | ||
163 | { | ||
164 | if (t2 >= t1) | ||
165 | return (t2 - t1); | ||
166 | else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER)) | ||
167 | return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); | ||
168 | else | ||
169 | return ((0xFFFFFFFF - t1) + t2); | ||
170 | } | ||
171 | |||
172 | static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) | ||
173 | { | ||
174 | if (t2 >= t1) | ||
175 | return PM_TIMER_TICKS_TO_US(t2 - t1); | ||
176 | else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER)) | ||
177 | return PM_TIMER_TICKS_TO_US(((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); | ||
178 | else | ||
179 | return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); | ||
180 | } | ||
181 | 165 | ||
182 | /* | 166 | /* |
183 | * Callers should disable interrupts before the call and enable | 167 | * Callers should disable interrupts before the call and enable |
@@ -853,7 +837,8 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) | |||
853 | static int acpi_idle_enter_c1(struct cpuidle_device *dev, | 837 | static int acpi_idle_enter_c1(struct cpuidle_device *dev, |
854 | struct cpuidle_state *state) | 838 | struct cpuidle_state *state) |
855 | { | 839 | { |
856 | u32 t1, t2; | 840 | ktime_t kt1, kt2; |
841 | s64 idle_time; | ||
857 | struct acpi_processor *pr; | 842 | struct acpi_processor *pr; |
858 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 843 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
859 | 844 | ||
@@ -871,14 +856,15 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
871 | return 0; | 856 | return 0; |
872 | } | 857 | } |
873 | 858 | ||
874 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 859 | kt1 = ktime_get_real(); |
875 | acpi_idle_do_entry(cx); | 860 | acpi_idle_do_entry(cx); |
876 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 861 | kt2 = ktime_get_real(); |
862 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
877 | 863 | ||
878 | local_irq_enable(); | 864 | local_irq_enable(); |
879 | cx->usage++; | 865 | cx->usage++; |
880 | 866 | ||
881 | return ticks_elapsed_in_us(t1, t2); | 867 | return idle_time; |
882 | } | 868 | } |
883 | 869 | ||
884 | /** | 870 | /** |
@@ -891,8 +877,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
891 | { | 877 | { |
892 | struct acpi_processor *pr; | 878 | struct acpi_processor *pr; |
893 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 879 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
894 | u32 t1, t2; | 880 | ktime_t kt1, kt2; |
895 | int sleep_ticks = 0; | 881 | s64 idle_time; |
882 | s64 sleep_ticks = 0; | ||
896 | 883 | ||
897 | pr = __get_cpu_var(processors); | 884 | pr = __get_cpu_var(processors); |
898 | 885 | ||
@@ -925,18 +912,19 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
925 | if (cx->type == ACPI_STATE_C3) | 912 | if (cx->type == ACPI_STATE_C3) |
926 | ACPI_FLUSH_CPU_CACHE(); | 913 | ACPI_FLUSH_CPU_CACHE(); |
927 | 914 | ||
928 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 915 | kt1 = ktime_get_real(); |
929 | /* Tell the scheduler that we are going deep-idle: */ | 916 | /* Tell the scheduler that we are going deep-idle: */ |
930 | sched_clock_idle_sleep_event(); | 917 | sched_clock_idle_sleep_event(); |
931 | acpi_idle_do_entry(cx); | 918 | acpi_idle_do_entry(cx); |
932 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 919 | kt2 = ktime_get_real(); |
920 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
933 | 921 | ||
934 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) | 922 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) |
935 | /* TSC could halt in idle, so notify users */ | 923 | /* TSC could halt in idle, so notify users */ |
936 | if (tsc_halts_in_c(cx->type)) | 924 | if (tsc_halts_in_c(cx->type)) |
937 | mark_tsc_unstable("TSC halts in idle");; | 925 | mark_tsc_unstable("TSC halts in idle");; |
938 | #endif | 926 | #endif |
939 | sleep_ticks = ticks_elapsed(t1, t2); | 927 | sleep_ticks = us_to_pm_timer_ticks(idle_time); |
940 | 928 | ||
941 | /* Tell the scheduler how much we idled: */ | 929 | /* Tell the scheduler how much we idled: */ |
942 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | 930 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); |
@@ -948,7 +936,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
948 | 936 | ||
949 | acpi_state_timer_broadcast(pr, cx, 0); | 937 | acpi_state_timer_broadcast(pr, cx, 0); |
950 | cx->time += sleep_ticks; | 938 | cx->time += sleep_ticks; |
951 | return ticks_elapsed_in_us(t1, t2); | 939 | return idle_time; |
952 | } | 940 | } |
953 | 941 | ||
954 | static int c3_cpu_count; | 942 | static int c3_cpu_count; |
@@ -966,8 +954,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
966 | { | 954 | { |
967 | struct acpi_processor *pr; | 955 | struct acpi_processor *pr; |
968 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 956 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
969 | u32 t1, t2; | 957 | ktime_t kt1, kt2; |
970 | int sleep_ticks = 0; | 958 | s64 idle_time; |
959 | s64 sleep_ticks = 0; | ||
960 | |||
971 | 961 | ||
972 | pr = __get_cpu_var(processors); | 962 | pr = __get_cpu_var(processors); |
973 | 963 | ||
@@ -1034,9 +1024,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1034 | ACPI_FLUSH_CPU_CACHE(); | 1024 | ACPI_FLUSH_CPU_CACHE(); |
1035 | } | 1025 | } |
1036 | 1026 | ||
1037 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 1027 | kt1 = ktime_get_real(); |
1038 | acpi_idle_do_entry(cx); | 1028 | acpi_idle_do_entry(cx); |
1039 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 1029 | kt2 = ktime_get_real(); |
1030 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
1040 | 1031 | ||
1041 | /* Re-enable bus master arbitration */ | 1032 | /* Re-enable bus master arbitration */ |
1042 | if (pr->flags.bm_check && pr->flags.bm_control) { | 1033 | if (pr->flags.bm_check && pr->flags.bm_control) { |
@@ -1051,7 +1042,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1051 | if (tsc_halts_in_c(ACPI_STATE_C3)) | 1042 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
1052 | mark_tsc_unstable("TSC halts in idle"); | 1043 | mark_tsc_unstable("TSC halts in idle"); |
1053 | #endif | 1044 | #endif |
1054 | sleep_ticks = ticks_elapsed(t1, t2); | 1045 | sleep_ticks = us_to_pm_timer_ticks(idle_time); |
1055 | /* Tell the scheduler how much we idled: */ | 1046 | /* Tell the scheduler how much we idled: */ |
1056 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | 1047 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); |
1057 | 1048 | ||
@@ -1062,7 +1053,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1062 | 1053 | ||
1063 | acpi_state_timer_broadcast(pr, cx, 0); | 1054 | acpi_state_timer_broadcast(pr, cx, 0); |
1064 | cx->time += sleep_ticks; | 1055 | cx->time += sleep_ticks; |
1065 | return ticks_elapsed_in_us(t1, t2); | 1056 | return idle_time; |
1066 | } | 1057 | } |
1067 | 1058 | ||
1068 | struct cpuidle_driver acpi_idle_driver = { | 1059 | struct cpuidle_driver acpi_idle_driver = { |