diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-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 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 |
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. |
@@ -108,25 +111,6 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { | |||
108 | {}, | 111 | {}, |
109 | }; | 112 | }; |
110 | 113 | ||
111 | static 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 | |||
121 | static 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) | |||
802 | static int acpi_idle_enter_c1(struct cpuidle_device *dev, | 786 | static 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 | ||
903 | static int c3_cpu_count; | 891 | static 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 | ||
1017 | struct cpuidle_driver acpi_idle_driver = { | 1008 | struct cpuidle_driver acpi_idle_driver = { |