diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-09-22 09:50:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-22 11:30:41 -0400 |
commit | 3967684006f30c253bc6d4a6604d1bad4a7fc672 (patch) | |
tree | 762eff17c78cb4399b39d5d754fc0540f3042483 /arch/x86/kernel | |
parent | b8c7f1dc5ca4e0d10709182233cdab932cef593d (diff) |
x86: mce: Clean up thermal throttling state tracking code
Instead of a mess of three separate percpu variables, consolidate
the state into a single structure.
Also clean up therm_throt_process(), use cleaner and more
understandable variable names and a clearer logic.
This, without changing the logic, makes the code more
streamlined, more readable and smaller as well:
text data bss dec hex filename
1487 169 4 1660 67c therm_throt.o.before
1432 176 4 1612 64c therm_throt.o.after
Cc: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Cc: Huang Ying <ying.huang@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/therm_throt.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 63a56d147e4a..db80b577f601 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
@@ -34,20 +34,30 @@ | |||
34 | /* How long to wait between reporting thermal events */ | 34 | /* How long to wait between reporting thermal events */ |
35 | #define CHECK_INTERVAL (300 * HZ) | 35 | #define CHECK_INTERVAL (300 * HZ) |
36 | 36 | ||
37 | static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES; | 37 | /* |
38 | static DEFINE_PER_CPU(unsigned long, thermal_throttle_count); | 38 | * Current thermal throttling state: |
39 | static DEFINE_PER_CPU(bool, thermal_throttle_active); | 39 | */ |
40 | struct thermal_state { | ||
41 | bool is_throttled; | ||
42 | |||
43 | u64 next_check; | ||
44 | unsigned long throttle_count; | ||
45 | }; | ||
46 | |||
47 | static DEFINE_PER_CPU(struct thermal_state, thermal_state); | ||
40 | 48 | ||
41 | static atomic_t therm_throt_en = ATOMIC_INIT(0); | 49 | static atomic_t therm_throt_en = ATOMIC_INIT(0); |
42 | 50 | ||
43 | #ifdef CONFIG_SYSFS | 51 | #ifdef CONFIG_SYSFS |
44 | #define define_therm_throt_sysdev_one_ro(_name) \ | 52 | #define define_therm_throt_sysdev_one_ro(_name) \ |
45 | static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) | 53 | static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) |
46 | 54 | ||
47 | #define define_therm_throt_sysdev_show_func(name) \ | 55 | #define define_therm_throt_sysdev_show_func(name) \ |
48 | static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | 56 | \ |
49 | struct sysdev_attribute *attr, \ | 57 | static ssize_t therm_throt_sysdev_show_##name( \ |
50 | char *buf) \ | 58 | struct sys_device *dev, \ |
59 | struct sysdev_attribute *attr, \ | ||
60 | char *buf) \ | ||
51 | { \ | 61 | { \ |
52 | unsigned int cpu = dev->id; \ | 62 | unsigned int cpu = dev->id; \ |
53 | ssize_t ret; \ | 63 | ssize_t ret; \ |
@@ -55,7 +65,7 @@ static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | |||
55 | preempt_disable(); /* CPU hotplug */ \ | 65 | preempt_disable(); /* CPU hotplug */ \ |
56 | if (cpu_online(cpu)) \ | 66 | if (cpu_online(cpu)) \ |
57 | ret = sprintf(buf, "%lu\n", \ | 67 | ret = sprintf(buf, "%lu\n", \ |
58 | per_cpu(thermal_throttle_##name, cpu)); \ | 68 | per_cpu(thermal_state, cpu).name); \ |
59 | else \ | 69 | else \ |
60 | ret = 0; \ | 70 | ret = 0; \ |
61 | preempt_enable(); \ | 71 | preempt_enable(); \ |
@@ -63,11 +73,11 @@ static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | |||
63 | return ret; \ | 73 | return ret; \ |
64 | } | 74 | } |
65 | 75 | ||
66 | define_therm_throt_sysdev_show_func(count); | 76 | define_therm_throt_sysdev_show_func(throttle_count); |
67 | define_therm_throt_sysdev_one_ro(count); | 77 | define_therm_throt_sysdev_one_ro(throttle_count); |
68 | 78 | ||
69 | static struct attribute *thermal_throttle_attrs[] = { | 79 | static struct attribute *thermal_throttle_attrs[] = { |
70 | &attr_count.attr, | 80 | &attr_throttle_count.attr, |
71 | NULL | 81 | NULL |
72 | }; | 82 | }; |
73 | 83 | ||
@@ -93,33 +103,38 @@ static struct attribute_group thermal_throttle_attr_group = { | |||
93 | * 1 : Event should be logged further, and a message has been | 103 | * 1 : Event should be logged further, and a message has been |
94 | * printed to the syslog. | 104 | * printed to the syslog. |
95 | */ | 105 | */ |
96 | static int therm_throt_process(int curr) | 106 | static int therm_throt_process(bool is_throttled) |
97 | { | 107 | { |
98 | unsigned int cpu = smp_processor_id(); | 108 | struct thermal_state *state; |
99 | __u64 tmp_jiffs = get_jiffies_64(); | 109 | unsigned int this_cpu; |
100 | bool was_throttled = __get_cpu_var(thermal_throttle_active); | 110 | bool was_throttled; |
101 | bool is_throttled = __get_cpu_var(thermal_throttle_active) = curr; | 111 | u64 now; |
112 | |||
113 | this_cpu = smp_processor_id(); | ||
114 | now = get_jiffies_64(); | ||
115 | state = &per_cpu(thermal_state, this_cpu); | ||
116 | |||
117 | was_throttled = state->is_throttled; | ||
118 | state->is_throttled = is_throttled; | ||
102 | 119 | ||
103 | if (is_throttled) | 120 | if (is_throttled) |
104 | __get_cpu_var(thermal_throttle_count)++; | 121 | state->throttle_count++; |
105 | 122 | ||
106 | if (!(was_throttled ^ is_throttled) && | 123 | if (!(was_throttled ^ is_throttled) && |
107 | time_before64(tmp_jiffs, __get_cpu_var(next_check))) | 124 | time_before64(now, state->next_check)) |
108 | return 0; | 125 | return 0; |
109 | 126 | ||
110 | __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL; | 127 | state->next_check = now + CHECK_INTERVAL; |
111 | 128 | ||
112 | /* if we just entered the thermal event */ | 129 | /* if we just entered the thermal event */ |
113 | if (is_throttled) { | 130 | if (is_throttled) { |
114 | printk(KERN_CRIT "CPU%d: Temperature above threshold, " | 131 | printk(KERN_CRIT "CPU%d: Temperature above threshold, cpu clock throttled (total events = %lu)\n", this_cpu, state->throttle_count); |
115 | "cpu clock throttled (total events = %lu)\n", | ||
116 | cpu, __get_cpu_var(thermal_throttle_count)); | ||
117 | 132 | ||
118 | add_taint(TAINT_MACHINE_CHECK); | 133 | add_taint(TAINT_MACHINE_CHECK); |
119 | return 1; | 134 | return 1; |
120 | } | 135 | } |
121 | if (was_throttled) { | 136 | if (was_throttled) { |
122 | printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu); | 137 | printk(KERN_INFO "CPU%d: Temperature/speed normal\n", this_cpu); |
123 | return 1; | 138 | return 1; |
124 | } | 139 | } |
125 | 140 | ||
@@ -213,7 +228,7 @@ static void intel_thermal_interrupt(void) | |||
213 | __u64 msr_val; | 228 | __u64 msr_val; |
214 | 229 | ||
215 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); | 230 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); |
216 | if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT)) | 231 | if (therm_throt_process((msr_val & THERM_STATUS_PROCHOT) != 0)) |
217 | mce_log_therm_throt_event(msr_val); | 232 | mce_log_therm_throt_event(msr_val); |
218 | } | 233 | } |
219 | 234 | ||