aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-06 13:02:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-06 13:02:58 -0400
commita5e11599da95fbe8425db0cfd01a581d7412d0c9 (patch)
tree45fccb4b27a1068cec8dc8283260893b60ca46d2
parent0f477dd0851bdcee82923da66a7fc4a44cb1bc3d (diff)
parenta3159864f2978bf2ace9cc787d73d315c98bbf9a (diff)
Merge branch 'x86-hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86, hwmon: Package Level Thermal/Power: pkgtemp documentation x86, hwmon: Package Level Thermal/Power: power limit x86, hwmon: Package Level Thermal/Power: thermal throttling handler x86, hwmon: Package Level Thermal/Power: pkgtemp hwmon driver
-rw-r--r--Documentation/hwmon/pkgtemp36
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c206
-rw-r--r--drivers/hwmon/Kconfig7
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/pkgtemp.c456
7 files changed, 669 insertions, 39 deletions
diff --git a/Documentation/hwmon/pkgtemp b/Documentation/hwmon/pkgtemp
new file mode 100644
index 000000000000..c8e1fb0fadd3
--- /dev/null
+++ b/Documentation/hwmon/pkgtemp
@@ -0,0 +1,36 @@
1Kernel driver pkgtemp
2======================
3
4Supported chips:
5 * Intel family
6 Prefix: 'pkgtemp'
7 CPUID:
8 Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual
9 Volume 3A: System Programming Guide
10
11Author: Fenghua Yu
12
13Description
14-----------
15
16This driver permits reading package level temperature sensor embedded inside
17Intel CPU package. The sensors can be in core, uncore, memory controller, or
18other components in a package. The feature is first implemented in Intel Sandy
19Bridge platform.
20
21Temperature is measured in degrees Celsius and measurement resolution is
221 degree C. Valid temperatures are from 0 to TjMax degrees C, because the actual
23value of temperature register is in fact a delta from TjMax.
24
25Temperature known as TjMax is the maximum junction temperature of package.
26We get this from MSR_IA32_TEMPERATURE_TARGET. If the MSR is not accessible,
27we define TjMax as 100 degrees Celsius. At this temperature, protection
28mechanism will perform actions to forcibly cool down the package. Alarm
29may be raised, if the temperature grows enough (more than TjMax) to trigger
30the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
31
32temp1_input - Package temperature (in millidegrees Celsius).
33temp1_max - All cooling devices should be turned on.
34temp1_crit - Maximum junction temperature (in millidegrees Celsius).
35temp1_crit_alarm - Set when Out-of-spec bit is set, never clears.
36 Correct CPU operation is no longer guaranteed.
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index d28fad19654a..e3a32431ca1e 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -1471,6 +1471,7 @@ CONFIG_HWMON=y
1471# CONFIG_SENSORS_GL518SM is not set 1471# CONFIG_SENSORS_GL518SM is not set
1472# CONFIG_SENSORS_GL520SM is not set 1472# CONFIG_SENSORS_GL520SM is not set
1473# CONFIG_SENSORS_CORETEMP is not set 1473# CONFIG_SENSORS_CORETEMP is not set
1474# CONFIG_SENSORS_PKGTEMP is not set
1474# CONFIG_SENSORS_IT87 is not set 1475# CONFIG_SENSORS_IT87 is not set
1475# CONFIG_SENSORS_LM63 is not set 1476# CONFIG_SENSORS_LM63 is not set
1476# CONFIG_SENSORS_LM75 is not set 1477# CONFIG_SENSORS_LM75 is not set
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 6c86acd847a4..4251f8372050 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -1456,6 +1456,7 @@ CONFIG_HWMON=y
1456# CONFIG_SENSORS_GL518SM is not set 1456# CONFIG_SENSORS_GL518SM is not set
1457# CONFIG_SENSORS_GL520SM is not set 1457# CONFIG_SENSORS_GL520SM is not set
1458# CONFIG_SENSORS_CORETEMP is not set 1458# CONFIG_SENSORS_CORETEMP is not set
1459# CONFIG_SENSORS_PKGTEMP is not set
1459# CONFIG_SENSORS_IT87 is not set 1460# CONFIG_SENSORS_IT87 is not set
1460# CONFIG_SENSORS_LM63 is not set 1461# CONFIG_SENSORS_LM63 is not set
1461# CONFIG_SENSORS_LM75 is not set 1462# CONFIG_SENSORS_LM75 is not set
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index e1a0a3bf9716..c2a8b26d4fea 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -34,15 +34,25 @@
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#define THERMAL_THROTTLING_EVENT 0
38#define POWER_LIMIT_EVENT 1
39
37/* 40/*
38 * Current thermal throttling state: 41 * Current thermal event state:
39 */ 42 */
40struct thermal_state { 43struct _thermal_state {
41 bool is_throttled; 44 bool new_event;
42 45 int event;
43 u64 next_check; 46 u64 next_check;
44 unsigned long throttle_count; 47 unsigned long count;
45 unsigned long last_throttle_count; 48 unsigned long last_count;
49};
50
51struct thermal_state {
52 struct _thermal_state core_throttle;
53 struct _thermal_state core_power_limit;
54 struct _thermal_state package_throttle;
55 struct _thermal_state package_power_limit;
46}; 56};
47 57
48static DEFINE_PER_CPU(struct thermal_state, thermal_state); 58static DEFINE_PER_CPU(struct thermal_state, thermal_state);
@@ -53,11 +63,13 @@ static u32 lvtthmr_init __read_mostly;
53 63
54#ifdef CONFIG_SYSFS 64#ifdef CONFIG_SYSFS
55#define define_therm_throt_sysdev_one_ro(_name) \ 65#define define_therm_throt_sysdev_one_ro(_name) \
56 static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) 66 static SYSDEV_ATTR(_name, 0444, \
67 therm_throt_sysdev_show_##_name, \
68 NULL) \
57 69
58#define define_therm_throt_sysdev_show_func(name) \ 70#define define_therm_throt_sysdev_show_func(event, name) \
59 \ 71 \
60static ssize_t therm_throt_sysdev_show_##name( \ 72static ssize_t therm_throt_sysdev_show_##event##_##name( \
61 struct sys_device *dev, \ 73 struct sys_device *dev, \
62 struct sysdev_attribute *attr, \ 74 struct sysdev_attribute *attr, \
63 char *buf) \ 75 char *buf) \
@@ -66,30 +78,42 @@ static ssize_t therm_throt_sysdev_show_##name( \
66 ssize_t ret; \ 78 ssize_t ret; \
67 \ 79 \
68 preempt_disable(); /* CPU hotplug */ \ 80 preempt_disable(); /* CPU hotplug */ \
69 if (cpu_online(cpu)) \ 81 if (cpu_online(cpu)) { \
70 ret = sprintf(buf, "%lu\n", \ 82 ret = sprintf(buf, "%lu\n", \
71 per_cpu(thermal_state, cpu).name); \ 83 per_cpu(thermal_state, cpu).event.name); \
72 else \ 84 } else \
73 ret = 0; \ 85 ret = 0; \
74 preempt_enable(); \ 86 preempt_enable(); \
75 \ 87 \
76 return ret; \ 88 return ret; \
77} 89}
78 90
79define_therm_throt_sysdev_show_func(throttle_count); 91define_therm_throt_sysdev_show_func(core_throttle, count);
80define_therm_throt_sysdev_one_ro(throttle_count); 92define_therm_throt_sysdev_one_ro(core_throttle_count);
93
94define_therm_throt_sysdev_show_func(core_power_limit, count);
95define_therm_throt_sysdev_one_ro(core_power_limit_count);
96
97define_therm_throt_sysdev_show_func(package_throttle, count);
98define_therm_throt_sysdev_one_ro(package_throttle_count);
99
100define_therm_throt_sysdev_show_func(package_power_limit, count);
101define_therm_throt_sysdev_one_ro(package_power_limit_count);
81 102
82static struct attribute *thermal_throttle_attrs[] = { 103static struct attribute *thermal_throttle_attrs[] = {
83 &attr_throttle_count.attr, 104 &attr_core_throttle_count.attr,
84 NULL 105 NULL
85}; 106};
86 107
87static struct attribute_group thermal_throttle_attr_group = { 108static struct attribute_group thermal_attr_group = {
88 .attrs = thermal_throttle_attrs, 109 .attrs = thermal_throttle_attrs,
89 .name = "thermal_throttle" 110 .name = "thermal_throttle"
90}; 111};
91#endif /* CONFIG_SYSFS */ 112#endif /* CONFIG_SYSFS */
92 113
114#define CORE_LEVEL 0
115#define PACKAGE_LEVEL 1
116
93/*** 117/***
94 * therm_throt_process - Process thermal throttling event from interrupt 118 * therm_throt_process - Process thermal throttling event from interrupt
95 * @curr: Whether the condition is current or not (boolean), since the 119 * @curr: Whether the condition is current or not (boolean), since the
@@ -106,39 +130,70 @@ static struct attribute_group thermal_throttle_attr_group = {
106 * 1 : Event should be logged further, and a message has been 130 * 1 : Event should be logged further, and a message has been
107 * printed to the syslog. 131 * printed to the syslog.
108 */ 132 */
109static int therm_throt_process(bool is_throttled) 133static int therm_throt_process(bool new_event, int event, int level)
110{ 134{
111 struct thermal_state *state; 135 struct _thermal_state *state;
112 unsigned int this_cpu; 136 unsigned int this_cpu = smp_processor_id();
113 bool was_throttled; 137 bool old_event;
114 u64 now; 138 u64 now;
139 struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
115 140
116 this_cpu = smp_processor_id();
117 now = get_jiffies_64(); 141 now = get_jiffies_64();
118 state = &per_cpu(thermal_state, this_cpu); 142 if (level == CORE_LEVEL) {
143 if (event == THERMAL_THROTTLING_EVENT)
144 state = &pstate->core_throttle;
145 else if (event == POWER_LIMIT_EVENT)
146 state = &pstate->core_power_limit;
147 else
148 return 0;
149 } else if (level == PACKAGE_LEVEL) {
150 if (event == THERMAL_THROTTLING_EVENT)
151 state = &pstate->package_throttle;
152 else if (event == POWER_LIMIT_EVENT)
153 state = &pstate->package_power_limit;
154 else
155 return 0;
156 } else
157 return 0;
119 158
120 was_throttled = state->is_throttled; 159 old_event = state->new_event;
121 state->is_throttled = is_throttled; 160 state->new_event = new_event;
122 161
123 if (is_throttled) 162 if (new_event)
124 state->throttle_count++; 163 state->count++;
125 164
126 if (time_before64(now, state->next_check) && 165 if (time_before64(now, state->next_check) &&
127 state->throttle_count != state->last_throttle_count) 166 state->count != state->last_count)
128 return 0; 167 return 0;
129 168
130 state->next_check = now + CHECK_INTERVAL; 169 state->next_check = now + CHECK_INTERVAL;
131 state->last_throttle_count = state->throttle_count; 170 state->last_count = state->count;
132 171
133 /* if we just entered the thermal event */ 172 /* if we just entered the thermal event */
134 if (is_throttled) { 173 if (new_event) {
135 printk(KERN_CRIT "CPU%d: Temperature above threshold, cpu clock throttled (total events = %lu)\n", this_cpu, state->throttle_count); 174 if (event == THERMAL_THROTTLING_EVENT)
175 printk(KERN_CRIT "CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
176 this_cpu,
177 level == CORE_LEVEL ? "Core" : "Package",
178 state->count);
179 else
180 printk(KERN_CRIT "CPU%d: %s power limit notification (total events = %lu)\n",
181 this_cpu,
182 level == CORE_LEVEL ? "Core" : "Package",
183 state->count);
136 184
137 add_taint(TAINT_MACHINE_CHECK); 185 add_taint(TAINT_MACHINE_CHECK);
138 return 1; 186 return 1;
139 } 187 }
140 if (was_throttled) { 188 if (old_event) {
141 printk(KERN_INFO "CPU%d: Temperature/speed normal\n", this_cpu); 189 if (event == THERMAL_THROTTLING_EVENT)
190 printk(KERN_INFO "CPU%d: %s temperature/speed normal\n",
191 this_cpu,
192 level == CORE_LEVEL ? "Core" : "Package");
193 else
194 printk(KERN_INFO "CPU%d: %s power limit normal\n",
195 this_cpu,
196 level == CORE_LEVEL ? "Core" : "Package");
142 return 1; 197 return 1;
143 } 198 }
144 199
@@ -149,13 +204,32 @@ static int therm_throt_process(bool is_throttled)
149/* Add/Remove thermal_throttle interface for CPU device: */ 204/* Add/Remove thermal_throttle interface for CPU device: */
150static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev) 205static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
151{ 206{
152 return sysfs_create_group(&sys_dev->kobj, 207 int err;
153 &thermal_throttle_attr_group); 208 struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
209
210 err = sysfs_create_group(&sys_dev->kobj, &thermal_attr_group);
211 if (err)
212 return err;
213
214 if (cpu_has(c, X86_FEATURE_PLN))
215 err = sysfs_add_file_to_group(&sys_dev->kobj,
216 &attr_core_power_limit_count.attr,
217 thermal_attr_group.name);
218 if (cpu_has(c, X86_FEATURE_PTS))
219 err = sysfs_add_file_to_group(&sys_dev->kobj,
220 &attr_package_throttle_count.attr,
221 thermal_attr_group.name);
222 if (cpu_has(c, X86_FEATURE_PLN))
223 err = sysfs_add_file_to_group(&sys_dev->kobj,
224 &attr_package_power_limit_count.attr,
225 thermal_attr_group.name);
226
227 return err;
154} 228}
155 229
156static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev) 230static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
157{ 231{
158 sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group); 232 sysfs_remove_group(&sys_dev->kobj, &thermal_attr_group);
159} 233}
160 234
161/* Mutex protecting device creation against CPU hotplug: */ 235/* Mutex protecting device creation against CPU hotplug: */
@@ -226,14 +300,50 @@ device_initcall(thermal_throttle_init_device);
226 300
227#endif /* CONFIG_SYSFS */ 301#endif /* CONFIG_SYSFS */
228 302
303/*
304 * Set up the most two significant bit to notify mce log that this thermal
305 * event type.
306 * This is a temp solution. May be changed in the future with mce log
307 * infrasture.
308 */
309#define CORE_THROTTLED (0)
310#define CORE_POWER_LIMIT ((__u64)1 << 62)
311#define PACKAGE_THROTTLED ((__u64)2 << 62)
312#define PACKAGE_POWER_LIMIT ((__u64)3 << 62)
313
229/* Thermal transition interrupt handler */ 314/* Thermal transition interrupt handler */
230static void intel_thermal_interrupt(void) 315static void intel_thermal_interrupt(void)
231{ 316{
232 __u64 msr_val; 317 __u64 msr_val;
318 struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
233 319
234 rdmsrl(MSR_IA32_THERM_STATUS, msr_val); 320 rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
235 if (therm_throt_process((msr_val & THERM_STATUS_PROCHOT) != 0)) 321
236 mce_log_therm_throt_event(msr_val); 322 if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT,
323 THERMAL_THROTTLING_EVENT,
324 CORE_LEVEL) != 0)
325 mce_log_therm_throt_event(CORE_THROTTLED | msr_val);
326
327 if (cpu_has(c, X86_FEATURE_PLN))
328 if (therm_throt_process(msr_val & THERM_STATUS_POWER_LIMIT,
329 POWER_LIMIT_EVENT,
330 CORE_LEVEL) != 0)
331 mce_log_therm_throt_event(CORE_POWER_LIMIT | msr_val);
332
333 if (cpu_has(c, X86_FEATURE_PTS)) {
334 rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
335 if (therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
336 THERMAL_THROTTLING_EVENT,
337 PACKAGE_LEVEL) != 0)
338 mce_log_therm_throt_event(PACKAGE_THROTTLED | msr_val);
339 if (cpu_has(c, X86_FEATURE_PLN))
340 if (therm_throt_process(msr_val &
341 PACKAGE_THERM_STATUS_POWER_LIMIT,
342 POWER_LIMIT_EVENT,
343 PACKAGE_LEVEL) != 0)
344 mce_log_therm_throt_event(PACKAGE_POWER_LIMIT
345 | msr_val);
346 }
237} 347}
238 348
239static void unexpected_thermal_interrupt(void) 349static void unexpected_thermal_interrupt(void)
@@ -335,8 +445,26 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
335 apic_write(APIC_LVTTHMR, h); 445 apic_write(APIC_LVTTHMR, h);
336 446
337 rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); 447 rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
338 wrmsr(MSR_IA32_THERM_INTERRUPT, 448 if (cpu_has(c, X86_FEATURE_PLN))
339 l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h); 449 wrmsr(MSR_IA32_THERM_INTERRUPT,
450 l | (THERM_INT_LOW_ENABLE
451 | THERM_INT_HIGH_ENABLE | THERM_INT_PLN_ENABLE), h);
452 else
453 wrmsr(MSR_IA32_THERM_INTERRUPT,
454 l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
455
456 if (cpu_has(c, X86_FEATURE_PTS)) {
457 rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
458 if (cpu_has(c, X86_FEATURE_PLN))
459 wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
460 l | (PACKAGE_THERM_INT_LOW_ENABLE
461 | PACKAGE_THERM_INT_HIGH_ENABLE
462 | PACKAGE_THERM_INT_PLN_ENABLE), h);
463 else
464 wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
465 l | (PACKAGE_THERM_INT_LOW_ENABLE
466 | PACKAGE_THERM_INT_HIGH_ENABLE), h);
467 }
340 468
341 smp_thermal_vector = intel_thermal_interrupt; 469 smp_thermal_vector = intel_thermal_interrupt;
342 470
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c57e530d07c7..4d382ae53092 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -407,6 +407,13 @@ config SENSORS_CORETEMP
407 sensor inside your CPU. Most of the family 6 CPUs 407 sensor inside your CPU. Most of the family 6 CPUs
408 are supported. Check documentation/driver for details. 408 are supported. Check documentation/driver for details.
409 409
410config SENSORS_PKGTEMP
411 tristate "Intel processor package temperature sensor"
412 depends on X86 && PCI && EXPERIMENTAL
413 help
414 If you say yes here you get support for the package level temperature
415 sensor inside your CPU. Check documentation/driver for details.
416
410config SENSORS_IBMAEM 417config SENSORS_IBMAEM
411 tristate "IBM Active Energy Manager temperature/power sensors and control" 418 tristate "IBM Active Energy Manager temperature/power sensors and control"
412 select IPMI_SI 419 select IPMI_SI
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index c5057745b068..9103bd6ea73a 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_SENSORS_AMS) += ams/
39obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o 39obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
40obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o 40obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
41obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o 41obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
42obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o
42obj-$(CONFIG_SENSORS_DME1737) += dme1737.o 43obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
43obj-$(CONFIG_SENSORS_DS1621) += ds1621.o 44obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
44obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o 45obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o
diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c
new file mode 100644
index 000000000000..74157fcda6ed
--- /dev/null
+++ b/drivers/hwmon/pkgtemp.c
@@ -0,0 +1,456 @@
1/*
2 * pkgtemp.c - Linux kernel module for processor package hardware monitoring
3 *
4 * Copyright (C) 2010 Fenghua Yu <fenghua.yu@intel.com>
5 *
6 * Inspired from many hwmon drivers especially coretemp.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23#include <linux/module.h>
24#include <linux/delay.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/jiffies.h>
28#include <linux/hwmon.h>
29#include <linux/sysfs.h>
30#include <linux/hwmon-sysfs.h>
31#include <linux/err.h>
32#include <linux/mutex.h>
33#include <linux/list.h>
34#include <linux/platform_device.h>
35#include <linux/cpu.h>
36#include <linux/pci.h>
37#include <asm/msr.h>
38#include <asm/processor.h>
39
40#define DRVNAME "pkgtemp"
41
42enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL, SHOW_NAME };
43
44/*
45 * Functions declaration
46 */
47
48static struct pkgtemp_data *pkgtemp_update_device(struct device *dev);
49
50struct pkgtemp_data {
51 struct device *hwmon_dev;
52 struct mutex update_lock;
53 const char *name;
54 u32 id;
55 u16 phys_proc_id;
56 char valid; /* zero until following fields are valid */
57 unsigned long last_updated; /* in jiffies */
58 int temp;
59 int tjmax;
60 int ttarget;
61 u8 alarm;
62};
63
64/*
65 * Sysfs stuff
66 */
67
68static ssize_t show_name(struct device *dev, struct device_attribute
69 *devattr, char *buf)
70{
71 int ret;
72 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
73 struct pkgtemp_data *data = dev_get_drvdata(dev);
74
75 if (attr->index == SHOW_NAME)
76 ret = sprintf(buf, "%s\n", data->name);
77 else /* show label */
78 ret = sprintf(buf, "physical id %d\n",
79 data->phys_proc_id);
80 return ret;
81}
82
83static ssize_t show_alarm(struct device *dev, struct device_attribute
84 *devattr, char *buf)
85{
86 struct pkgtemp_data *data = pkgtemp_update_device(dev);
87 /* read the Out-of-spec log, never clear */
88 return sprintf(buf, "%d\n", data->alarm);
89}
90
91static ssize_t show_temp(struct device *dev,
92 struct device_attribute *devattr, char *buf)
93{
94 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
95 struct pkgtemp_data *data = pkgtemp_update_device(dev);
96 int err = 0;
97
98 if (attr->index == SHOW_TEMP)
99 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
100 else if (attr->index == SHOW_TJMAX)
101 err = sprintf(buf, "%d\n", data->tjmax);
102 else
103 err = sprintf(buf, "%d\n", data->ttarget);
104 return err;
105}
106
107static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, SHOW_TEMP);
108static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, SHOW_TJMAX);
109static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, SHOW_TTARGET);
110static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
111static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
112static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
113
114static struct attribute *pkgtemp_attributes[] = {
115 &sensor_dev_attr_name.dev_attr.attr,
116 &sensor_dev_attr_temp1_label.dev_attr.attr,
117 &dev_attr_temp1_crit_alarm.attr,
118 &sensor_dev_attr_temp1_input.dev_attr.attr,
119 &sensor_dev_attr_temp1_crit.dev_attr.attr,
120 NULL
121};
122
123static const struct attribute_group pkgtemp_group = {
124 .attrs = pkgtemp_attributes,
125};
126
127static struct pkgtemp_data *pkgtemp_update_device(struct device *dev)
128{
129 struct pkgtemp_data *data = dev_get_drvdata(dev);
130 unsigned int cpu;
131 int err;
132
133 mutex_lock(&data->update_lock);
134
135 if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
136 u32 eax, edx;
137
138 data->valid = 0;
139 cpu = data->id;
140 err = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_STATUS,
141 &eax, &edx);
142 if (!err) {
143 data->alarm = (eax >> 5) & 1;
144 data->temp = data->tjmax - (((eax >> 16)
145 & 0x7f) * 1000);
146 data->valid = 1;
147 } else
148 dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
149
150 data->last_updated = jiffies;
151 }
152
153 mutex_unlock(&data->update_lock);
154 return data;
155}
156
157static int get_tjmax(int cpu, struct device *dev)
158{
159 int default_tjmax = 100000;
160 int err;
161 u32 eax, edx;
162 u32 val;
163
164 /* IA32_TEMPERATURE_TARGET contains the TjMax value */
165 err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
166 if (!err) {
167 val = (eax >> 16) & 0xff;
168 if ((val > 80) && (val < 120)) {
169 dev_info(dev, "TjMax is %d C.\n", val);
170 return val * 1000;
171 }
172 }
173 dev_warn(dev, "Unable to read TjMax from CPU.\n");
174 return default_tjmax;
175}
176
177static int __devinit pkgtemp_probe(struct platform_device *pdev)
178{
179 struct pkgtemp_data *data;
180 int err;
181 u32 eax, edx;
182#ifdef CONFIG_SMP
183 struct cpuinfo_x86 *c = &cpu_data(pdev->id);
184#endif
185
186 data = kzalloc(sizeof(struct pkgtemp_data), GFP_KERNEL);
187 if (!data) {
188 err = -ENOMEM;
189 dev_err(&pdev->dev, "Out of memory\n");
190 goto exit;
191 }
192
193 data->id = pdev->id;
194#ifdef CONFIG_SMP
195 data->phys_proc_id = c->phys_proc_id;
196#endif
197 data->name = "pkgtemp";
198 mutex_init(&data->update_lock);
199
200 /* test if we can access the THERM_STATUS MSR */
201 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_STATUS,
202 &eax, &edx);
203 if (err) {
204 dev_err(&pdev->dev,
205 "Unable to access THERM_STATUS MSR, giving up\n");
206 goto exit_free;
207 }
208
209 data->tjmax = get_tjmax(data->id, &pdev->dev);
210 platform_set_drvdata(pdev, data);
211
212 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET,
213 &eax, &edx);
214 if (err) {
215 dev_warn(&pdev->dev, "Unable to read"
216 " IA32_TEMPERATURE_TARGET MSR\n");
217 } else {
218 data->ttarget = data->tjmax - (((eax >> 8) & 0xff) * 1000);
219 err = device_create_file(&pdev->dev,
220 &sensor_dev_attr_temp1_max.dev_attr);
221 if (err)
222 goto exit_free;
223 }
224
225 err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group);
226 if (err)
227 goto exit_free;
228
229 data->hwmon_dev = hwmon_device_register(&pdev->dev);
230 if (IS_ERR(data->hwmon_dev)) {
231 err = PTR_ERR(data->hwmon_dev);
232 dev_err(&pdev->dev, "Class registration failed (%d)\n",
233 err);
234 goto exit_class;
235 }
236
237 return 0;
238
239exit_class:
240 sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
241exit_free:
242 kfree(data);
243exit:
244 return err;
245}
246
247static int __devexit pkgtemp_remove(struct platform_device *pdev)
248{
249 struct pkgtemp_data *data = platform_get_drvdata(pdev);
250
251 hwmon_device_unregister(data->hwmon_dev);
252 sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
253 platform_set_drvdata(pdev, NULL);
254 kfree(data);
255 return 0;
256}
257
258static struct platform_driver pkgtemp_driver = {
259 .driver = {
260 .owner = THIS_MODULE,
261 .name = DRVNAME,
262 },
263 .probe = pkgtemp_probe,
264 .remove = __devexit_p(pkgtemp_remove),
265};
266
267struct pdev_entry {
268 struct list_head list;
269 struct platform_device *pdev;
270 unsigned int cpu;
271#ifdef CONFIG_SMP
272 u16 phys_proc_id;
273#endif
274};
275
276static LIST_HEAD(pdev_list);
277static DEFINE_MUTEX(pdev_list_mutex);
278
279static int __cpuinit pkgtemp_device_add(unsigned int cpu)
280{
281 int err;
282 struct platform_device *pdev;
283 struct pdev_entry *pdev_entry;
284#ifdef CONFIG_SMP
285 struct cpuinfo_x86 *c = &cpu_data(cpu);
286#endif
287
288 mutex_lock(&pdev_list_mutex);
289
290#ifdef CONFIG_SMP
291 /* Only keep the first entry in each package */
292 list_for_each_entry(pdev_entry, &pdev_list, list) {
293 if (c->phys_proc_id == pdev_entry->phys_proc_id) {
294 err = 0; /* Not an error */
295 goto exit;
296 }
297 }
298#endif
299
300 pdev = platform_device_alloc(DRVNAME, cpu);
301 if (!pdev) {
302 err = -ENOMEM;
303 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
304 goto exit;
305 }
306
307 pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
308 if (!pdev_entry) {
309 err = -ENOMEM;
310 goto exit_device_put;
311 }
312
313 err = platform_device_add(pdev);
314 if (err) {
315 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
316 err);
317 goto exit_device_free;
318 }
319
320#ifdef CONFIG_SMP
321 pdev_entry->phys_proc_id = c->phys_proc_id;
322#endif
323 pdev_entry->pdev = pdev;
324 pdev_entry->cpu = cpu;
325 list_add_tail(&pdev_entry->list, &pdev_list);
326 mutex_unlock(&pdev_list_mutex);
327
328 return 0;
329
330exit_device_free:
331 kfree(pdev_entry);
332exit_device_put:
333 platform_device_put(pdev);
334exit:
335 mutex_unlock(&pdev_list_mutex);
336 return err;
337}
338
339#ifdef CONFIG_HOTPLUG_CPU
340static void pkgtemp_device_remove(unsigned int cpu)
341{
342 struct pdev_entry *p, *n;
343 unsigned int i;
344 int err;
345
346 mutex_lock(&pdev_list_mutex);
347 list_for_each_entry_safe(p, n, &pdev_list, list) {
348 if (p->cpu != cpu)
349 continue;
350
351 platform_device_unregister(p->pdev);
352 list_del(&p->list);
353 kfree(p);
354 for_each_cpu(i, cpu_core_mask(cpu)) {
355 if (i != cpu) {
356 err = pkgtemp_device_add(i);
357 if (!err)
358 break;
359 }
360 }
361 break;
362 }
363 mutex_unlock(&pdev_list_mutex);
364}
365
366static int __cpuinit pkgtemp_cpu_callback(struct notifier_block *nfb,
367 unsigned long action, void *hcpu)
368{
369 unsigned int cpu = (unsigned long) hcpu;
370
371 switch (action) {
372 case CPU_ONLINE:
373 case CPU_DOWN_FAILED:
374 pkgtemp_device_add(cpu);
375 break;
376 case CPU_DOWN_PREPARE:
377 pkgtemp_device_remove(cpu);
378 break;
379 }
380 return NOTIFY_OK;
381}
382
383static struct notifier_block pkgtemp_cpu_notifier __refdata = {
384 .notifier_call = pkgtemp_cpu_callback,
385};
386#endif /* !CONFIG_HOTPLUG_CPU */
387
388static int __init pkgtemp_init(void)
389{
390 int i, err = -ENODEV;
391 struct pdev_entry *p, *n;
392
393 /* quick check if we run Intel */
394 if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
395 goto exit;
396
397 err = platform_driver_register(&pkgtemp_driver);
398 if (err)
399 goto exit;
400
401 for_each_online_cpu(i) {
402 struct cpuinfo_x86 *c = &cpu_data(i);
403
404 if (!cpu_has(c, X86_FEATURE_PTS))
405 continue;
406
407 err = pkgtemp_device_add(i);
408 if (err)
409 goto exit_devices_unreg;
410 }
411 if (list_empty(&pdev_list)) {
412 err = -ENODEV;
413 goto exit_driver_unreg;
414 }
415
416#ifdef CONFIG_HOTPLUG_CPU
417 register_hotcpu_notifier(&pkgtemp_cpu_notifier);
418#endif
419 return 0;
420
421exit_devices_unreg:
422 mutex_lock(&pdev_list_mutex);
423 list_for_each_entry_safe(p, n, &pdev_list, list) {
424 platform_device_unregister(p->pdev);
425 list_del(&p->list);
426 kfree(p);
427 }
428 mutex_unlock(&pdev_list_mutex);
429exit_driver_unreg:
430 platform_driver_unregister(&pkgtemp_driver);
431exit:
432 return err;
433}
434
435static void __exit pkgtemp_exit(void)
436{
437 struct pdev_entry *p, *n;
438#ifdef CONFIG_HOTPLUG_CPU
439 unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
440#endif
441 mutex_lock(&pdev_list_mutex);
442 list_for_each_entry_safe(p, n, &pdev_list, list) {
443 platform_device_unregister(p->pdev);
444 list_del(&p->list);
445 kfree(p);
446 }
447 mutex_unlock(&pdev_list_mutex);
448 platform_driver_unregister(&pkgtemp_driver);
449}
450
451MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
452MODULE_DESCRIPTION("Intel processor package temperature monitor");
453MODULE_LICENSE("GPL");
454
455module_init(pkgtemp_init)
456module_exit(pkgtemp_exit)