Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec...
[pandora-kernel.git] / arch / x86 / kernel / cpu / mcheck / therm_throt.c
1 /*
2  * Thermal throttle event support code (such as syslog messaging and rate
3  * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
4  *
5  * This allows consistent reporting of CPU thermal throttle events.
6  *
7  * Maintains a counter in /sys that keeps track of the number of thermal
8  * events, such that the user knows how bad the thermal problem might be
9  * (since the logging to syslog and mcelog is rate limited).
10  *
11  * Author: Dmitriy Zavin (dmitriyz@google.com)
12  *
13  * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
14  *          Inspired by Ross Biro's and Al Borchers' counter code.
15  */
16 #include <linux/interrupt.h>
17 #include <linux/notifier.h>
18 #include <linux/jiffies.h>
19 #include <linux/kernel.h>
20 #include <linux/percpu.h>
21 #include <linux/sysdev.h>
22 #include <linux/types.h>
23 #include <linux/init.h>
24 #include <linux/smp.h>
25 #include <linux/cpu.h>
26
27 #include <asm/processor.h>
28 #include <asm/system.h>
29 #include <asm/apic.h>
30 #include <asm/idle.h>
31 #include <asm/mce.h>
32 #include <asm/msr.h>
33
34 /* How long to wait between reporting thermal events */
35 #define CHECK_INTERVAL          (300 * HZ)
36
37 static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
38 static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
39
40 static atomic_t therm_throt_en          = ATOMIC_INIT(0);
41
42 #ifdef CONFIG_SYSFS
43 #define define_therm_throt_sysdev_one_ro(_name)                         \
44         static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
45
46 #define define_therm_throt_sysdev_show_func(name)                       \
47 static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev,   \
48                                         struct sysdev_attribute *attr,  \
49                                               char *buf)                \
50 {                                                                       \
51         unsigned int cpu = dev->id;                                     \
52         ssize_t ret;                                                    \
53                                                                         \
54         preempt_disable();      /* CPU hotplug */                       \
55         if (cpu_online(cpu))                                            \
56                 ret = sprintf(buf, "%lu\n",                             \
57                               per_cpu(thermal_throttle_##name, cpu));   \
58         else                                                            \
59                 ret = 0;                                                \
60         preempt_enable();                                               \
61                                                                         \
62         return ret;                                                     \
63 }
64
65 define_therm_throt_sysdev_show_func(count);
66 define_therm_throt_sysdev_one_ro(count);
67
68 static struct attribute *thermal_throttle_attrs[] = {
69         &attr_count.attr,
70         NULL
71 };
72
73 static struct attribute_group thermal_throttle_attr_group = {
74         .attrs  = thermal_throttle_attrs,
75         .name   = "thermal_throttle"
76 };
77 #endif /* CONFIG_SYSFS */
78
79 /***
80  * therm_throt_process - Process thermal throttling event from interrupt
81  * @curr: Whether the condition is current or not (boolean), since the
82  *        thermal interrupt normally gets called both when the thermal
83  *        event begins and once the event has ended.
84  *
85  * This function is called by the thermal interrupt after the
86  * IRQ has been acknowledged.
87  *
88  * It will take care of rate limiting and printing messages to the syslog.
89  *
90  * Returns: 0 : Event should NOT be further logged, i.e. still in
91  *              "timeout" from previous log message.
92  *          1 : Event should be logged further, and a message has been
93  *              printed to the syslog.
94  */
95 static int therm_throt_process(int curr)
96 {
97         unsigned int cpu = smp_processor_id();
98         __u64 tmp_jiffs = get_jiffies_64();
99
100         if (curr)
101                 __get_cpu_var(thermal_throttle_count)++;
102
103         if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
104                 return 0;
105
106         __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
107
108         /* if we just entered the thermal event */
109         if (curr) {
110                 printk(KERN_CRIT "CPU%d: Temperature above threshold, "
111                        "cpu clock throttled (total events = %lu)\n", cpu,
112                        __get_cpu_var(thermal_throttle_count));
113
114                 add_taint(TAINT_MACHINE_CHECK);
115         } else {
116                 printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
117         }
118
119         return 1;
120 }
121
122 #ifdef CONFIG_SYSFS
123 /* Add/Remove thermal_throttle interface for CPU device: */
124 static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
125 {
126         return sysfs_create_group(&sys_dev->kobj,
127                                   &thermal_throttle_attr_group);
128 }
129
130 static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
131 {
132         sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
133 }
134
135 /* Mutex protecting device creation against CPU hotplug: */
136 static DEFINE_MUTEX(therm_cpu_lock);
137
138 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
139 static __cpuinit int
140 thermal_throttle_cpu_callback(struct notifier_block *nfb,
141                               unsigned long action,
142                               void *hcpu)
143 {
144         unsigned int cpu = (unsigned long)hcpu;
145         struct sys_device *sys_dev;
146         int err = 0;
147
148         sys_dev = get_cpu_sysdev(cpu);
149
150         switch (action) {
151         case CPU_UP_PREPARE:
152         case CPU_UP_PREPARE_FROZEN:
153                 mutex_lock(&therm_cpu_lock);
154                 err = thermal_throttle_add_dev(sys_dev);
155                 mutex_unlock(&therm_cpu_lock);
156                 WARN_ON(err);
157                 break;
158         case CPU_UP_CANCELED:
159         case CPU_UP_CANCELED_FROZEN:
160         case CPU_DEAD:
161         case CPU_DEAD_FROZEN:
162                 mutex_lock(&therm_cpu_lock);
163                 thermal_throttle_remove_dev(sys_dev);
164                 mutex_unlock(&therm_cpu_lock);
165                 break;
166         }
167         return err ? NOTIFY_BAD : NOTIFY_OK;
168 }
169
170 static struct notifier_block thermal_throttle_cpu_notifier __cpuinitdata =
171 {
172         .notifier_call = thermal_throttle_cpu_callback,
173 };
174
175 static __init int thermal_throttle_init_device(void)
176 {
177         unsigned int cpu = 0;
178         int err;
179
180         if (!atomic_read(&therm_throt_en))
181                 return 0;
182
183         register_hotcpu_notifier(&thermal_throttle_cpu_notifier);
184
185 #ifdef CONFIG_HOTPLUG_CPU
186         mutex_lock(&therm_cpu_lock);
187 #endif
188         /* connect live CPUs to sysfs */
189         for_each_online_cpu(cpu) {
190                 err = thermal_throttle_add_dev(get_cpu_sysdev(cpu));
191                 WARN_ON(err);
192         }
193 #ifdef CONFIG_HOTPLUG_CPU
194         mutex_unlock(&therm_cpu_lock);
195 #endif
196
197         return 0;
198 }
199 device_initcall(thermal_throttle_init_device);
200
201 #endif /* CONFIG_SYSFS */
202
203 /* Thermal transition interrupt handler */
204 static void intel_thermal_interrupt(void)
205 {
206         __u64 msr_val;
207
208         rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
209         if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
210                 mce_log_therm_throt_event(msr_val);
211 }
212
213 static void unexpected_thermal_interrupt(void)
214 {
215         printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
216                         smp_processor_id());
217         add_taint(TAINT_MACHINE_CHECK);
218 }
219
220 static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
221
222 asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
223 {
224         exit_idle();
225         irq_enter();
226         inc_irq_stat(irq_thermal_count);
227         smp_thermal_vector();
228         irq_exit();
229         /* Ack only at the end to avoid potential reentry */
230         ack_APIC_irq();
231 }
232
233 void intel_init_thermal(struct cpuinfo_x86 *c)
234 {
235         unsigned int cpu = smp_processor_id();
236         int tm2 = 0;
237         u32 l, h;
238
239         /* Thermal monitoring depends on ACPI and clock modulation*/
240         if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
241                 return;
242
243         /*
244          * First check if its enabled already, in which case there might
245          * be some SMM goo which handles it, so we can't even put a handler
246          * since it might be delivered via SMI already:
247          */
248         rdmsr(MSR_IA32_MISC_ENABLE, l, h);
249         h = apic_read(APIC_LVTTHMR);
250         if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
251                 printk(KERN_DEBUG
252                        "CPU%d: Thermal monitoring handled by SMI\n", cpu);
253                 return;
254         }
255
256         if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2))
257                 tm2 = 1;
258
259         /* Check whether a vector already exists */
260         if (h & APIC_VECTOR_MASK) {
261                 printk(KERN_DEBUG
262                        "CPU%d: Thermal LVT vector (%#x) already installed\n",
263                        cpu, (h & APIC_VECTOR_MASK));
264                 return;
265         }
266
267         /* We'll mask the thermal vector in the lapic till we're ready: */
268         h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
269         apic_write(APIC_LVTTHMR, h);
270
271         rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
272         wrmsr(MSR_IA32_THERM_INTERRUPT,
273                 l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
274
275         smp_thermal_vector = intel_thermal_interrupt;
276
277         rdmsr(MSR_IA32_MISC_ENABLE, l, h);
278         wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
279
280         /* Unmask the thermal vector: */
281         l = apic_read(APIC_LVTTHMR);
282         apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
283
284         printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
285                cpu, tm2 ? "TM2" : "TM1");
286
287         /* enable thermal throttle processing */
288         atomic_set(&therm_throt_en, 1);
289 }