diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r-- | drivers/acpi/processor_idle.c | 124 |
1 files changed, 32 insertions, 92 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7bc22a471fe3..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. |
@@ -101,57 +104,6 @@ static int set_max_cstate(const struct dmi_system_id *id) | |||
101 | /* Actually this shouldn't be __cpuinitdata, would be better to fix the | 104 | /* Actually this shouldn't be __cpuinitdata, would be better to fix the |
102 | callers to only run once -AK */ | 105 | callers to only run once -AK */ |
103 | static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { | 106 | static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { |
104 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
105 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
106 | DMI_MATCH(DMI_BIOS_VERSION,"1SET70WW")}, (void *)1}, | ||
107 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
108 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
109 | DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, | ||
110 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
111 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
112 | DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1}, | ||
113 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
114 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
115 | DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1}, | ||
116 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
117 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
118 | DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1}, | ||
119 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
120 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
121 | DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1}, | ||
122 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
123 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
124 | DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1}, | ||
125 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
126 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
127 | DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1}, | ||
128 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
129 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
130 | DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1}, | ||
131 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
132 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
133 | DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1}, | ||
134 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
135 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
136 | DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, | ||
137 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
138 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
139 | DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1}, | ||
140 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
141 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
142 | DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1}, | ||
143 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
144 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
145 | DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1}, | ||
146 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
147 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
148 | DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1}, | ||
149 | { set_max_cstate, "IBM ThinkPad R40e", { | ||
150 | DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), | ||
151 | DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1}, | ||
152 | { set_max_cstate, "Medion 41700", { | ||
153 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), | ||
154 | DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1}, | ||
155 | { set_max_cstate, "Clevo 5600D", { | 107 | { set_max_cstate, "Clevo 5600D", { |
156 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), | 108 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), |
157 | DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, | 109 | DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, |
@@ -159,25 +111,6 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { | |||
159 | {}, | 111 | {}, |
160 | }; | 112 | }; |
161 | 113 | ||
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 | 114 | ||
182 | /* | 115 | /* |
183 | * Callers should disable interrupts before the call and enable | 116 | * Callers should disable interrupts before the call and enable |
@@ -630,7 +563,7 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
630 | * In either case, the proper way to | 563 | * In either case, the proper way to |
631 | * handle BM_RLD is to set it and leave it set. | 564 | * handle BM_RLD is to set it and leave it set. |
632 | */ | 565 | */ |
633 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); | 566 | acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1); |
634 | 567 | ||
635 | return; | 568 | return; |
636 | } | 569 | } |
@@ -800,9 +733,9 @@ static int acpi_idle_bm_check(void) | |||
800 | { | 733 | { |
801 | u32 bm_status = 0; | 734 | u32 bm_status = 0; |
802 | 735 | ||
803 | acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); | 736 | acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); |
804 | if (bm_status) | 737 | if (bm_status) |
805 | acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); | 738 | acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); |
806 | /* | 739 | /* |
807 | * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect | 740 | * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect |
808 | * the true state of bus mastering activity; forcing us to | 741 | * the true state of bus mastering activity; forcing us to |
@@ -853,7 +786,8 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) | |||
853 | static int acpi_idle_enter_c1(struct cpuidle_device *dev, | 786 | static int acpi_idle_enter_c1(struct cpuidle_device *dev, |
854 | struct cpuidle_state *state) | 787 | struct cpuidle_state *state) |
855 | { | 788 | { |
856 | u32 t1, t2; | 789 | ktime_t kt1, kt2; |
790 | s64 idle_time; | ||
857 | struct acpi_processor *pr; | 791 | struct acpi_processor *pr; |
858 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 792 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
859 | 793 | ||
@@ -871,14 +805,15 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
871 | return 0; | 805 | return 0; |
872 | } | 806 | } |
873 | 807 | ||
874 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 808 | kt1 = ktime_get_real(); |
875 | acpi_idle_do_entry(cx); | 809 | acpi_idle_do_entry(cx); |
876 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 810 | kt2 = ktime_get_real(); |
811 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
877 | 812 | ||
878 | local_irq_enable(); | 813 | local_irq_enable(); |
879 | cx->usage++; | 814 | cx->usage++; |
880 | 815 | ||
881 | return ticks_elapsed_in_us(t1, t2); | 816 | return idle_time; |
882 | } | 817 | } |
883 | 818 | ||
884 | /** | 819 | /** |
@@ -891,8 +826,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
891 | { | 826 | { |
892 | struct acpi_processor *pr; | 827 | struct acpi_processor *pr; |
893 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 828 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
894 | u32 t1, t2; | 829 | ktime_t kt1, kt2; |
895 | int sleep_ticks = 0; | 830 | s64 idle_time; |
831 | s64 sleep_ticks = 0; | ||
896 | 832 | ||
897 | pr = __get_cpu_var(processors); | 833 | pr = __get_cpu_var(processors); |
898 | 834 | ||
@@ -925,18 +861,19 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
925 | if (cx->type == ACPI_STATE_C3) | 861 | if (cx->type == ACPI_STATE_C3) |
926 | ACPI_FLUSH_CPU_CACHE(); | 862 | ACPI_FLUSH_CPU_CACHE(); |
927 | 863 | ||
928 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 864 | kt1 = ktime_get_real(); |
929 | /* Tell the scheduler that we are going deep-idle: */ | 865 | /* Tell the scheduler that we are going deep-idle: */ |
930 | sched_clock_idle_sleep_event(); | 866 | sched_clock_idle_sleep_event(); |
931 | acpi_idle_do_entry(cx); | 867 | acpi_idle_do_entry(cx); |
932 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 868 | kt2 = ktime_get_real(); |
869 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
933 | 870 | ||
934 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) | 871 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) |
935 | /* TSC could halt in idle, so notify users */ | 872 | /* TSC could halt in idle, so notify users */ |
936 | if (tsc_halts_in_c(cx->type)) | 873 | if (tsc_halts_in_c(cx->type)) |
937 | mark_tsc_unstable("TSC halts in idle");; | 874 | mark_tsc_unstable("TSC halts in idle");; |
938 | #endif | 875 | #endif |
939 | sleep_ticks = ticks_elapsed(t1, t2); | 876 | sleep_ticks = us_to_pm_timer_ticks(idle_time); |
940 | 877 | ||
941 | /* Tell the scheduler how much we idled: */ | 878 | /* Tell the scheduler how much we idled: */ |
942 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | 879 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); |
@@ -948,7 +885,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
948 | 885 | ||
949 | acpi_state_timer_broadcast(pr, cx, 0); | 886 | acpi_state_timer_broadcast(pr, cx, 0); |
950 | cx->time += sleep_ticks; | 887 | cx->time += sleep_ticks; |
951 | return ticks_elapsed_in_us(t1, t2); | 888 | return idle_time; |
952 | } | 889 | } |
953 | 890 | ||
954 | static int c3_cpu_count; | 891 | static int c3_cpu_count; |
@@ -966,8 +903,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
966 | { | 903 | { |
967 | struct acpi_processor *pr; | 904 | struct acpi_processor *pr; |
968 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 905 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
969 | u32 t1, t2; | 906 | ktime_t kt1, kt2; |
970 | int sleep_ticks = 0; | 907 | s64 idle_time; |
908 | s64 sleep_ticks = 0; | ||
909 | |||
971 | 910 | ||
972 | pr = __get_cpu_var(processors); | 911 | pr = __get_cpu_var(processors); |
973 | 912 | ||
@@ -1028,20 +967,21 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1028 | c3_cpu_count++; | 967 | c3_cpu_count++; |
1029 | /* Disable bus master arbitration when all CPUs are in C3 */ | 968 | /* Disable bus master arbitration when all CPUs are in C3 */ |
1030 | if (c3_cpu_count == num_online_cpus()) | 969 | if (c3_cpu_count == num_online_cpus()) |
1031 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); | 970 | acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); |
1032 | spin_unlock(&c3_lock); | 971 | spin_unlock(&c3_lock); |
1033 | } else if (!pr->flags.bm_check) { | 972 | } else if (!pr->flags.bm_check) { |
1034 | ACPI_FLUSH_CPU_CACHE(); | 973 | ACPI_FLUSH_CPU_CACHE(); |
1035 | } | 974 | } |
1036 | 975 | ||
1037 | t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 976 | kt1 = ktime_get_real(); |
1038 | acpi_idle_do_entry(cx); | 977 | acpi_idle_do_entry(cx); |
1039 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 978 | kt2 = ktime_get_real(); |
979 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | ||
1040 | 980 | ||
1041 | /* Re-enable bus master arbitration */ | 981 | /* Re-enable bus master arbitration */ |
1042 | if (pr->flags.bm_check && pr->flags.bm_control) { | 982 | if (pr->flags.bm_check && pr->flags.bm_control) { |
1043 | spin_lock(&c3_lock); | 983 | spin_lock(&c3_lock); |
1044 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); | 984 | acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); |
1045 | c3_cpu_count--; | 985 | c3_cpu_count--; |
1046 | spin_unlock(&c3_lock); | 986 | spin_unlock(&c3_lock); |
1047 | } | 987 | } |
@@ -1051,7 +991,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1051 | if (tsc_halts_in_c(ACPI_STATE_C3)) | 991 | if (tsc_halts_in_c(ACPI_STATE_C3)) |
1052 | mark_tsc_unstable("TSC halts in idle"); | 992 | mark_tsc_unstable("TSC halts in idle"); |
1053 | #endif | 993 | #endif |
1054 | sleep_ticks = ticks_elapsed(t1, t2); | 994 | sleep_ticks = us_to_pm_timer_ticks(idle_time); |
1055 | /* Tell the scheduler how much we idled: */ | 995 | /* Tell the scheduler how much we idled: */ |
1056 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | 996 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); |
1057 | 997 | ||
@@ -1062,7 +1002,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1062 | 1002 | ||
1063 | acpi_state_timer_broadcast(pr, cx, 0); | 1003 | acpi_state_timer_broadcast(pr, cx, 0); |
1064 | cx->time += sleep_ticks; | 1004 | cx->time += sleep_ticks; |
1065 | return ticks_elapsed_in_us(t1, t2); | 1005 | return idle_time; |
1066 | } | 1006 | } |
1067 | 1007 | ||
1068 | struct cpuidle_driver acpi_idle_driver = { | 1008 | struct cpuidle_driver acpi_idle_driver = { |