Blame view
drivers/hwmon/coretemp.c
20.6 KB
bebe46782 hwmon: New corete... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* * coretemp.c - Linux kernel module for hardware monitoring * * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz> * * Inspired from many hwmon drivers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ |
f8bb89256 hwmon: (coretemp)... |
22 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
bebe46782 hwmon: New corete... |
23 |
#include <linux/module.h> |
bebe46782 hwmon: New corete... |
24 25 26 27 28 29 30 31 32 33 34 |
#include <linux/init.h> #include <linux/slab.h> #include <linux/jiffies.h> #include <linux/hwmon.h> #include <linux/sysfs.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> #include <linux/list.h> #include <linux/platform_device.h> #include <linux/cpu.h> |
1fe63ab47 hwmon: (coretemp)... |
35 |
#include <linux/pci.h> |
4cc452758 hwmon: (coretemp)... |
36 |
#include <linux/smp.h> |
a45a8c857 hwmon: (coretemp)... |
37 |
#include <linux/moduleparam.h> |
bebe46782 hwmon: New corete... |
38 39 40 41 |
#include <asm/msr.h> #include <asm/processor.h> #define DRVNAME "coretemp" |
a45a8c857 hwmon: (coretemp)... |
42 43 44 45 46 47 48 |
/* * force_tjmax only matters when TjMax can't be read from the CPU itself. * When set, it replaces the driver's suboptimal heuristic. */ static int force_tjmax; module_param_named(tjmax, force_tjmax, int, 0444); MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); |
199e0de7f hwmon: (coretemp)... |
49 50 51 |
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ #define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ |
c814a4c7c hwmon: (coretemp)... |
52 |
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
f4af6fd6e hwmon: (coretemp)... |
53 |
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) |
199e0de7f hwmon: (coretemp)... |
54 |
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) |
199e0de7f hwmon: (coretemp)... |
55 56 |
#define TO_PHYS_ID(cpu) cpu_data(cpu).phys_proc_id #define TO_CORE_ID(cpu) cpu_data(cpu).cpu_core_id |
141168c36 x86: Simplify cod... |
57 58 59 |
#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) #ifdef CONFIG_SMP |
bb74e8ca3 hwmon: (coretemp)... |
60 |
#define for_each_sibling(i, cpu) for_each_cpu(i, cpu_sibling_mask(cpu)) |
199e0de7f hwmon: (coretemp)... |
61 |
#else |
bb74e8ca3 hwmon: (coretemp)... |
62 |
#define for_each_sibling(i, cpu) for (i = 0; false; ) |
199e0de7f hwmon: (coretemp)... |
63 |
#endif |
bebe46782 hwmon: New corete... |
64 65 |
/* |
199e0de7f hwmon: (coretemp)... |
66 67 68 69 70 71 72 |
* Per-Core Temperature Data * @last_updated: The time when the current temperature value was updated * earlier (in jiffies). * @cpu_core_id: The CPU Core from which temperature values should be read * This value is passed as "id" field to rdmsr/wrmsr functions. * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, * from where the temperature values should be read. |
c814a4c7c hwmon: (coretemp)... |
73 |
* @attr_size: Total number of pre-core attrs displayed in the sysfs. |
199e0de7f hwmon: (coretemp)... |
74 75 76 |
* @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. * Otherwise, temp_data holds coretemp data. * @valid: If this is 1, the current temperature is valid. |
bebe46782 hwmon: New corete... |
77 |
*/ |
199e0de7f hwmon: (coretemp)... |
78 |
struct temp_data { |
bebe46782 hwmon: New corete... |
79 |
int temp; |
6369a2887 hwmon: (coretemp)... |
80 |
int ttarget; |
199e0de7f hwmon: (coretemp)... |
81 82 83 84 85 |
int tjmax; unsigned long last_updated; unsigned int cpu; u32 cpu_core_id; u32 status_reg; |
c814a4c7c hwmon: (coretemp)... |
86 |
int attr_size; |
199e0de7f hwmon: (coretemp)... |
87 88 |
bool is_pkg_data; bool valid; |
c814a4c7c hwmon: (coretemp)... |
89 90 |
struct sensor_device_attribute sd_attrs[TOTAL_ATTRS]; char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH]; |
199e0de7f hwmon: (coretemp)... |
91 |
struct mutex update_lock; |
bebe46782 hwmon: New corete... |
92 |
}; |
199e0de7f hwmon: (coretemp)... |
93 94 95 96 97 98 99 |
/* Platform Data per Physical CPU */ struct platform_data { struct device *hwmon_dev; u16 phys_proc_id; struct temp_data *core_data[MAX_CORE_DATA]; struct device_attribute name_attr; }; |
bebe46782 hwmon: New corete... |
100 |
|
199e0de7f hwmon: (coretemp)... |
101 102 103 |
struct pdev_entry { struct list_head list; struct platform_device *pdev; |
199e0de7f hwmon: (coretemp)... |
104 |
u16 phys_proc_id; |
199e0de7f hwmon: (coretemp)... |
105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
}; static LIST_HEAD(pdev_list); static DEFINE_MUTEX(pdev_list_mutex); static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { return sprintf(buf, "%s ", DRVNAME); } static ssize_t show_label(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
119 |
{ |
bebe46782 hwmon: New corete... |
120 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
199e0de7f hwmon: (coretemp)... |
121 122 123 124 125 126 |
struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; if (tdata->is_pkg_data) return sprintf(buf, "Physical id %u ", pdata->phys_proc_id); |
bebe46782 hwmon: New corete... |
127 |
|
199e0de7f hwmon: (coretemp)... |
128 129 |
return sprintf(buf, "Core %u ", tdata->cpu_core_id); |
bebe46782 hwmon: New corete... |
130 |
} |
199e0de7f hwmon: (coretemp)... |
131 132 |
static ssize_t show_crit_alarm(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
133 |
{ |
199e0de7f hwmon: (coretemp)... |
134 135 136 137 138 139 140 141 142 |
u32 eax, edx; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); return sprintf(buf, "%d ", (eax >> 5) & 1); |
bebe46782 hwmon: New corete... |
143 |
} |
199e0de7f hwmon: (coretemp)... |
144 145 |
static ssize_t show_tjmax(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
146 147 |
{ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
199e0de7f hwmon: (coretemp)... |
148 |
struct platform_data *pdata = dev_get_drvdata(dev); |
bebe46782 hwmon: New corete... |
149 |
|
199e0de7f hwmon: (coretemp)... |
150 151 |
return sprintf(buf, "%d ", pdata->core_data[attr->index]->tjmax); |
bebe46782 hwmon: New corete... |
152 |
} |
199e0de7f hwmon: (coretemp)... |
153 154 155 156 157 |
static ssize_t show_ttarget(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct platform_data *pdata = dev_get_drvdata(dev); |
bebe46782 hwmon: New corete... |
158 |
|
199e0de7f hwmon: (coretemp)... |
159 160 161 |
return sprintf(buf, "%d ", pdata->core_data[attr->index]->ttarget); } |
bebe46782 hwmon: New corete... |
162 |
|
199e0de7f hwmon: (coretemp)... |
163 164 |
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
165 |
{ |
199e0de7f hwmon: (coretemp)... |
166 167 168 169 |
u32 eax, edx; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; |
bebe46782 hwmon: New corete... |
170 |
|
199e0de7f hwmon: (coretemp)... |
171 |
mutex_lock(&tdata->update_lock); |
bebe46782 hwmon: New corete... |
172 |
|
199e0de7f hwmon: (coretemp)... |
173 174 175 176 177 |
/* Check whether the time interval has elapsed */ if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); tdata->valid = 0; /* Check whether the data is valid */ |
bebe46782 hwmon: New corete... |
178 |
if (eax & 0x80000000) { |
199e0de7f hwmon: (coretemp)... |
179 |
tdata->temp = tdata->tjmax - |
4cc452758 hwmon: (coretemp)... |
180 |
((eax >> 16) & 0x7f) * 1000; |
199e0de7f hwmon: (coretemp)... |
181 |
tdata->valid = 1; |
bebe46782 hwmon: New corete... |
182 |
} |
199e0de7f hwmon: (coretemp)... |
183 |
tdata->last_updated = jiffies; |
bebe46782 hwmon: New corete... |
184 |
} |
199e0de7f hwmon: (coretemp)... |
185 186 187 |
mutex_unlock(&tdata->update_lock); return tdata->valid ? sprintf(buf, "%d ", tdata->temp) : -EAGAIN; |
bebe46782 hwmon: New corete... |
188 |
} |
d6db23c7c hwmon: (coretemp)... |
189 190 |
static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) |
118a88718 hwmon: (coretemp)... |
191 192 193 194 |
{ /* The 100C is default for both mobile and non mobile CPUs */ int tjmax = 100000; |
eccfed422 hwmon: (coretemp)... |
195 |
int tjmax_ee = 85000; |
708a62bcd hwmon: (coretemp)... |
196 |
int usemsr_ee = 1; |
118a88718 hwmon: (coretemp)... |
197 198 |
int err; u32 eax, edx; |
1fe63ab47 hwmon: (coretemp)... |
199 |
struct pci_dev *host_bridge; |
118a88718 hwmon: (coretemp)... |
200 201 |
/* Early chips have no MSR for TjMax */ |
4cc452758 hwmon: (coretemp)... |
202 |
if (c->x86_model == 0xf && c->x86_mask < 4) |
708a62bcd hwmon: (coretemp)... |
203 |
usemsr_ee = 0; |
118a88718 hwmon: (coretemp)... |
204 |
|
1fe63ab47 hwmon: (coretemp)... |
205 |
/* Atom CPUs */ |
708a62bcd hwmon: (coretemp)... |
206 207 208 |
if (c->x86_model == 0x1c) { usemsr_ee = 0; |
1fe63ab47 hwmon: (coretemp)... |
209 210 211 212 213 214 215 216 217 218 219 |
host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL && (host_bridge->device == 0xa000 /* NM10 based nettop */ || host_bridge->device == 0xa010)) /* NM10 based netbook */ tjmax = 100000; else tjmax = 90000; pci_dev_put(host_bridge); |
708a62bcd hwmon: (coretemp)... |
220 |
} |
4cc452758 hwmon: (coretemp)... |
221 |
if (c->x86_model > 0xe && usemsr_ee) { |
eccfed422 hwmon: (coretemp)... |
222 |
u8 platform_id; |
118a88718 hwmon: (coretemp)... |
223 |
|
4cc452758 hwmon: (coretemp)... |
224 225 226 227 228 |
/* * Now we can detect the mobile CPU using Intel provided table * http://softwarecommunity.intel.com/Wiki/Mobility/720.htm * For Core2 cores, check MSR 0x17, bit 28 1 = Mobile CPU */ |
118a88718 hwmon: (coretemp)... |
229 230 231 232 233 234 |
err = rdmsr_safe_on_cpu(id, 0x17, &eax, &edx); if (err) { dev_warn(dev, "Unable to access MSR 0x17, assuming desktop" " CPU "); |
708a62bcd hwmon: (coretemp)... |
235 |
usemsr_ee = 0; |
eccfed422 hwmon: (coretemp)... |
236 |
} else if (c->x86_model < 0x17 && !(eax & 0x10000000)) { |
4cc452758 hwmon: (coretemp)... |
237 238 239 240 241 |
/* * Trust bit 28 up to Penryn, I could not find any * documentation on that; if you happen to know * someone at Intel please ask */ |
708a62bcd hwmon: (coretemp)... |
242 |
usemsr_ee = 0; |
eccfed422 hwmon: (coretemp)... |
243 244 245 |
} else { /* Platform ID bits 52:50 (EDX starts at bit 32) */ platform_id = (edx >> 18) & 0x7; |
4cc452758 hwmon: (coretemp)... |
246 247 248 249 250 251 252 253 254 255 |
/* * Mobile Penryn CPU seems to be platform ID 7 or 5 * (guesswork) */ if (c->x86_model == 0x17 && (platform_id == 5 || platform_id == 7)) { /* * If MSR EE bit is set, set it to 90 degrees C, * otherwise 105 degrees C */ |
eccfed422 hwmon: (coretemp)... |
256 257 258 |
tjmax_ee = 90000; tjmax = 105000; } |
118a88718 hwmon: (coretemp)... |
259 260 |
} } |
708a62bcd hwmon: (coretemp)... |
261 |
if (usemsr_ee) { |
118a88718 hwmon: (coretemp)... |
262 263 264 265 |
err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx); if (err) { dev_warn(dev, "Unable to access MSR 0xEE, for Tjmax, left" |
4d7a5644e hwmon: (coretemp)... |
266 267 |
" at default "); |
118a88718 hwmon: (coretemp)... |
268 |
} else if (eax & 0x40000000) { |
eccfed422 hwmon: (coretemp)... |
269 |
tjmax = tjmax_ee; |
118a88718 hwmon: (coretemp)... |
270 |
} |
708a62bcd hwmon: (coretemp)... |
271 |
} else if (tjmax == 100000) { |
4cc452758 hwmon: (coretemp)... |
272 273 274 275 |
/* * If we don't use msr EE it means we are desktop CPU * (with exeception of Atom) */ |
118a88718 hwmon: (coretemp)... |
276 277 278 279 280 281 |
dev_warn(dev, "Using relative temperature scale! "); } return tjmax; } |
d6db23c7c hwmon: (coretemp)... |
282 283 |
static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) |
a321cedb1 drivers/hwmon/cor... |
284 |
{ |
a321cedb1 drivers/hwmon/cor... |
285 286 287 |
int err; u32 eax, edx; u32 val; |
4cc452758 hwmon: (coretemp)... |
288 289 290 291 |
/* * A new feature of current Intel(R) processors, the * IA32_TEMPERATURE_TARGET contains the TjMax value */ |
a321cedb1 drivers/hwmon/cor... |
292 293 |
err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); if (err) { |
6bf9e9b09 hwmon: (coretemp)... |
294 295 296 |
if (c->x86_model > 0xe && c->x86_model != 0x1c) dev_warn(dev, "Unable to read TjMax from CPU %u ", id); |
a321cedb1 drivers/hwmon/cor... |
297 298 299 300 301 302 |
} else { val = (eax >> 16) & 0xff; /* * If the TjMax is not plausible, an assumption * will be used */ |
bb9973e4e hwmon: (coretemp)... |
303 |
if (val) { |
6bf9e9b09 hwmon: (coretemp)... |
304 305 |
dev_dbg(dev, "TjMax is %d degrees C ", val); |
a321cedb1 drivers/hwmon/cor... |
306 307 308 |
return val * 1000; } } |
a45a8c857 hwmon: (coretemp)... |
309 310 311 312 313 314 |
if (force_tjmax) { dev_notice(dev, "TjMax forced to %d degrees C by user ", force_tjmax); return force_tjmax * 1000; } |
a321cedb1 drivers/hwmon/cor... |
315 316 |
/* * An assumption is made for early CPUs and unreadable MSR. |
4f5f71a7a hwmon: (coretemp)... |
317 |
* NOTE: the calculated value may not be correct. |
a321cedb1 drivers/hwmon/cor... |
318 |
*/ |
4f5f71a7a hwmon: (coretemp)... |
319 |
return adjust_tjmax(c, id, dev); |
a321cedb1 drivers/hwmon/cor... |
320 |
} |
d6db23c7c hwmon: (coretemp)... |
321 322 |
static int __devinit create_name_attr(struct platform_data *pdata, struct device *dev) |
199e0de7f hwmon: (coretemp)... |
323 |
{ |
4258781ac hwmon: (coretemp)... |
324 |
sysfs_attr_init(&pdata->name_attr.attr); |
199e0de7f hwmon: (coretemp)... |
325 326 327 328 329 |
pdata->name_attr.attr.name = "name"; pdata->name_attr.attr.mode = S_IRUGO; pdata->name_attr.show = show_name; return device_create_file(dev, &pdata->name_attr); } |
bebe46782 hwmon: New corete... |
330 |
|
d6db23c7c hwmon: (coretemp)... |
331 332 |
static int __cpuinit create_core_attrs(struct temp_data *tdata, struct device *dev, int attr_no) |
199e0de7f hwmon: (coretemp)... |
333 334 |
{ int err, i; |
e3204ed3a hwmon: (coretemp)... |
335 |
static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, |
199e0de7f hwmon: (coretemp)... |
336 |
struct device_attribute *devattr, char *buf) = { |
c814a4c7c hwmon: (coretemp)... |
337 |
show_label, show_crit_alarm, show_temp, show_tjmax, |
f4af6fd6e hwmon: (coretemp)... |
338 |
show_ttarget }; |
e3204ed3a hwmon: (coretemp)... |
339 |
static const char *const names[TOTAL_ATTRS] = { |
199e0de7f hwmon: (coretemp)... |
340 |
"temp%d_label", "temp%d_crit_alarm", |
c814a4c7c hwmon: (coretemp)... |
341 |
"temp%d_input", "temp%d_crit", |
f4af6fd6e hwmon: (coretemp)... |
342 |
"temp%d_max" }; |
199e0de7f hwmon: (coretemp)... |
343 |
|
c814a4c7c hwmon: (coretemp)... |
344 |
for (i = 0; i < tdata->attr_size; i++) { |
199e0de7f hwmon: (coretemp)... |
345 346 |
snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], attr_no); |
4258781ac hwmon: (coretemp)... |
347 |
sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); |
199e0de7f hwmon: (coretemp)... |
348 349 350 |
tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; |
199e0de7f hwmon: (coretemp)... |
351 352 353 354 |
tdata->sd_attrs[i].index = attr_no; err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); if (err) goto exit_free; |
bebe46782 hwmon: New corete... |
355 |
} |
199e0de7f hwmon: (coretemp)... |
356 357 358 359 360 361 362 |
return 0; exit_free: while (--i >= 0) device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); return err; } |
199e0de7f hwmon: (coretemp)... |
363 |
|
0eb9782ad hwmon: (coretemp)... |
364 |
static int __cpuinit chk_ucode_version(unsigned int cpu) |
199e0de7f hwmon: (coretemp)... |
365 |
{ |
0eb9782ad hwmon: (coretemp)... |
366 |
struct cpuinfo_x86 *c = &cpu_data(cpu); |
67f363b1f hwmon/coretemp: A... |
367 |
|
199e0de7f hwmon: (coretemp)... |
368 369 370 371 372 |
/* * Check if we have problem with errata AE18 of Core processors: * Readings might stop update when processor visited too deep sleep, * fixed for stepping D0 (6EC). */ |
ca8bc8dc0 coretemp: Get mic... |
373 374 375 376 377 |
if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) { pr_err("Errata AE18 not fixed, update BIOS or " "microcode of the CPU! "); return -ENODEV; |
67f363b1f hwmon/coretemp: A... |
378 |
} |
199e0de7f hwmon: (coretemp)... |
379 380 |
return 0; } |
d6db23c7c hwmon: (coretemp)... |
381 |
static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu) |
199e0de7f hwmon: (coretemp)... |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
{ u16 phys_proc_id = TO_PHYS_ID(cpu); struct pdev_entry *p; mutex_lock(&pdev_list_mutex); list_for_each_entry(p, &pdev_list, list) if (p->phys_proc_id == phys_proc_id) { mutex_unlock(&pdev_list_mutex); return p->pdev; } mutex_unlock(&pdev_list_mutex); return NULL; } |
d6db23c7c hwmon: (coretemp)... |
397 398 |
static struct temp_data __cpuinit *init_temp_data(unsigned int cpu, int pkg_flag) |
199e0de7f hwmon: (coretemp)... |
399 400 401 402 403 404 405 406 407 408 409 410 |
{ struct temp_data *tdata; tdata = kzalloc(sizeof(struct temp_data), GFP_KERNEL); if (!tdata) return NULL; tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS; tdata->is_pkg_data = pkg_flag; tdata->cpu = cpu; tdata->cpu_core_id = TO_CORE_ID(cpu); |
c814a4c7c hwmon: (coretemp)... |
411 |
tdata->attr_size = MAX_CORE_ATTRS; |
199e0de7f hwmon: (coretemp)... |
412 413 414 |
mutex_init(&tdata->update_lock); return tdata; } |
67f363b1f hwmon/coretemp: A... |
415 |
|
d6db23c7c hwmon: (coretemp)... |
416 |
static int __cpuinit create_core_data(struct platform_device *pdev, |
199e0de7f hwmon: (coretemp)... |
417 418 419 |
unsigned int cpu, int pkg_flag) { struct temp_data *tdata; |
2f1c3db0a hwmon: (coretemp)... |
420 |
struct platform_data *pdata = platform_get_drvdata(pdev); |
199e0de7f hwmon: (coretemp)... |
421 422 423 |
struct cpuinfo_x86 *c = &cpu_data(cpu); u32 eax, edx; int err, attr_no; |
bebe46782 hwmon: New corete... |
424 |
|
a321cedb1 drivers/hwmon/cor... |
425 |
/* |
199e0de7f hwmon: (coretemp)... |
426 427 428 429 |
* Find attr number for sysfs: * We map the attr number to core id of the CPU * The attr number is always core id + 2 * The Pkgtemp will always show up as temp1_*, if available |
a321cedb1 drivers/hwmon/cor... |
430 |
*/ |
199e0de7f hwmon: (coretemp)... |
431 |
attr_no = pkg_flag ? 1 : TO_ATTR_NO(cpu); |
6369a2887 hwmon: (coretemp)... |
432 |
|
199e0de7f hwmon: (coretemp)... |
433 434 |
if (attr_no > MAX_CORE_DATA - 1) return -ERANGE; |
f4e0bcf06 hwmon: (coretemp)... |
435 436 437 |
/* * Provide a single set of attributes for all HT siblings of a core * to avoid duplicate sensors (the processor ID and core ID of all |
6777b9e47 hwmon: (coretemp)... |
438 439 |
* HT siblings of a core are the same). * Skip if a HT sibling of this core is already registered. |
f4e0bcf06 hwmon: (coretemp)... |
440 441 |
* This is not an error. */ |
199e0de7f hwmon: (coretemp)... |
442 443 |
if (pdata->core_data[attr_no] != NULL) return 0; |
6369a2887 hwmon: (coretemp)... |
444 |
|
199e0de7f hwmon: (coretemp)... |
445 446 447 |
tdata = init_temp_data(cpu, pkg_flag); if (!tdata) return -ENOMEM; |
bebe46782 hwmon: New corete... |
448 |
|
199e0de7f hwmon: (coretemp)... |
449 450 451 452 453 454 |
/* Test if we can access the status register */ err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx); if (err) goto exit_free; /* We can access status register. Get Critical Temperature */ |
6bf9e9b09 hwmon: (coretemp)... |
455 |
tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); |
199e0de7f hwmon: (coretemp)... |
456 |
|
c814a4c7c hwmon: (coretemp)... |
457 |
/* |
f4af6fd6e hwmon: (coretemp)... |
458 459 460 |
* Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET. * The target temperature is available on older CPUs but not in this * register. Atoms don't have the register at all. |
c814a4c7c hwmon: (coretemp)... |
461 |
*/ |
f4af6fd6e hwmon: (coretemp)... |
462 463 464 465 466 467 468 469 |
if (c->x86_model > 0xe && c->x86_model != 0x1c) { err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); if (!err) { tdata->ttarget = tdata->tjmax - ((eax >> 8) & 0xff) * 1000; tdata->attr_size++; } |
c814a4c7c hwmon: (coretemp)... |
470 |
} |
199e0de7f hwmon: (coretemp)... |
471 472 473 474 475 476 |
pdata->core_data[attr_no] = tdata; /* Create sysfs interfaces */ err = create_core_attrs(tdata, &pdev->dev, attr_no); if (err) goto exit_free; |
bebe46782 hwmon: New corete... |
477 478 |
return 0; |
199e0de7f hwmon: (coretemp)... |
479 |
exit_free: |
20ecb499f hwmon: (coretemp)... |
480 |
pdata->core_data[attr_no] = NULL; |
199e0de7f hwmon: (coretemp)... |
481 482 483 |
kfree(tdata); return err; } |
d6db23c7c hwmon: (coretemp)... |
484 |
static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag) |
199e0de7f hwmon: (coretemp)... |
485 |
{ |
199e0de7f hwmon: (coretemp)... |
486 487 488 489 490 |
struct platform_device *pdev = coretemp_get_pdev(cpu); int err; if (!pdev) return; |
2f1c3db0a hwmon: (coretemp)... |
491 |
err = create_core_data(pdev, cpu, pkg_flag); |
199e0de7f hwmon: (coretemp)... |
492 493 494 495 496 497 498 499 500 501 502 503 |
if (err) dev_err(&pdev->dev, "Adding Core %u failed ", cpu); } static void coretemp_remove_core(struct platform_data *pdata, struct device *dev, int indx) { int i; struct temp_data *tdata = pdata->core_data[indx]; /* Remove the sysfs attributes */ |
c814a4c7c hwmon: (coretemp)... |
504 |
for (i = 0; i < tdata->attr_size; i++) |
199e0de7f hwmon: (coretemp)... |
505 506 507 508 509 510 511 512 513 514 |
device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); kfree(pdata->core_data[indx]); pdata->core_data[indx] = NULL; } static int __devinit coretemp_probe(struct platform_device *pdev) { struct platform_data *pdata; int err; |
bebe46782 hwmon: New corete... |
515 |
|
199e0de7f hwmon: (coretemp)... |
516 517 518 519 520 521 522 523 |
/* Initialize the per-package data structures */ pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL); if (!pdata) return -ENOMEM; err = create_name_attr(pdata, &pdev->dev); if (err) goto exit_free; |
b3a242a6e hwmon: (coretemp)... |
524 |
pdata->phys_proc_id = pdev->id; |
199e0de7f hwmon: (coretemp)... |
525 526 527 528 529 530 531 532 533 534 535 536 537 538 |
platform_set_drvdata(pdev, pdata); pdata->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(pdata->hwmon_dev)) { err = PTR_ERR(pdata->hwmon_dev); dev_err(&pdev->dev, "Class registration failed (%d) ", err); goto exit_name; } return 0; exit_name: device_remove_file(&pdev->dev, &pdata->name_attr); platform_set_drvdata(pdev, NULL); |
bebe46782 hwmon: New corete... |
539 |
exit_free: |
199e0de7f hwmon: (coretemp)... |
540 |
kfree(pdata); |
bebe46782 hwmon: New corete... |
541 542 543 544 545 |
return err; } static int __devexit coretemp_remove(struct platform_device *pdev) { |
199e0de7f hwmon: (coretemp)... |
546 547 |
struct platform_data *pdata = platform_get_drvdata(pdev); int i; |
bebe46782 hwmon: New corete... |
548 |
|
199e0de7f hwmon: (coretemp)... |
549 550 551 552 553 554 |
for (i = MAX_CORE_DATA - 1; i >= 0; --i) if (pdata->core_data[i]) coretemp_remove_core(pdata, &pdev->dev, i); device_remove_file(&pdev->dev, &pdata->name_attr); hwmon_device_unregister(pdata->hwmon_dev); |
bebe46782 hwmon: New corete... |
555 |
platform_set_drvdata(pdev, NULL); |
199e0de7f hwmon: (coretemp)... |
556 |
kfree(pdata); |
bebe46782 hwmon: New corete... |
557 558 559 560 561 562 563 564 565 566 567 |
return 0; } static struct platform_driver coretemp_driver = { .driver = { .owner = THIS_MODULE, .name = DRVNAME, }, .probe = coretemp_probe, .remove = __devexit_p(coretemp_remove), }; |
bebe46782 hwmon: New corete... |
568 569 570 571 572 |
static int __cpuinit coretemp_device_add(unsigned int cpu) { int err; struct platform_device *pdev; struct pdev_entry *pdev_entry; |
d883b9f09 hwmon: (coretemp)... |
573 574 |
mutex_lock(&pdev_list_mutex); |
b3a242a6e hwmon: (coretemp)... |
575 |
pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu)); |
bebe46782 hwmon: New corete... |
576 577 |
if (!pdev) { err = -ENOMEM; |
f8bb89256 hwmon: (coretemp)... |
578 579 |
pr_err("Device allocation failed "); |
bebe46782 hwmon: New corete... |
580 581 582 583 584 585 586 587 588 589 590 |
goto exit; } pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); if (!pdev_entry) { err = -ENOMEM; goto exit_device_put; } err = platform_device_add(pdev); if (err) { |
f8bb89256 hwmon: (coretemp)... |
591 592 |
pr_err("Device addition failed (%d) ", err); |
bebe46782 hwmon: New corete... |
593 594 595 596 |
goto exit_device_free; } pdev_entry->pdev = pdev; |
0eb9782ad hwmon: (coretemp)... |
597 |
pdev_entry->phys_proc_id = pdev->id; |
199e0de7f hwmon: (coretemp)... |
598 |
|
bebe46782 hwmon: New corete... |
599 600 601 602 603 604 605 606 607 608 |
list_add_tail(&pdev_entry->list, &pdev_list); mutex_unlock(&pdev_list_mutex); return 0; exit_device_free: kfree(pdev_entry); exit_device_put: platform_device_put(pdev); exit: |
d883b9f09 hwmon: (coretemp)... |
609 |
mutex_unlock(&pdev_list_mutex); |
bebe46782 hwmon: New corete... |
610 611 |
return err; } |
d6db23c7c hwmon: (coretemp)... |
612 |
static void __cpuinit coretemp_device_remove(unsigned int cpu) |
bebe46782 hwmon: New corete... |
613 |
{ |
199e0de7f hwmon: (coretemp)... |
614 615 |
struct pdev_entry *p, *n; u16 phys_proc_id = TO_PHYS_ID(cpu); |
e40cc4bdf x86/hwmon: regist... |
616 |
|
bebe46782 hwmon: New corete... |
617 |
mutex_lock(&pdev_list_mutex); |
199e0de7f hwmon: (coretemp)... |
618 619 |
list_for_each_entry_safe(p, n, &pdev_list, list) { if (p->phys_proc_id != phys_proc_id) |
e40cc4bdf x86/hwmon: regist... |
620 |
continue; |
e40cc4bdf x86/hwmon: regist... |
621 622 |
platform_device_unregister(p->pdev); list_del(&p->list); |
e40cc4bdf x86/hwmon: regist... |
623 |
kfree(p); |
bebe46782 hwmon: New corete... |
624 625 626 |
} mutex_unlock(&pdev_list_mutex); } |
d6db23c7c hwmon: (coretemp)... |
627 |
static bool __cpuinit is_any_core_online(struct platform_data *pdata) |
199e0de7f hwmon: (coretemp)... |
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
{ int i; /* Find online cores, except pkgtemp data */ for (i = MAX_CORE_DATA - 1; i >= 0; --i) { if (pdata->core_data[i] && !pdata->core_data[i]->is_pkg_data) { return true; } } return false; } static void __cpuinit get_core_online(unsigned int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct platform_device *pdev = coretemp_get_pdev(cpu); int err; /* * CPUID.06H.EAX[0] indicates whether the CPU has thermal * sensors. We check this bit only, all the early CPUs * without thermal sensors will be filtered out. */ if (!cpu_has(c, X86_FEATURE_DTS)) return; if (!pdev) { |
0eb9782ad hwmon: (coretemp)... |
656 657 658 |
/* Check the microcode version of the CPU */ if (chk_ucode_version(cpu)) return; |
199e0de7f hwmon: (coretemp)... |
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
/* * Alright, we have DTS support. * We are bringing the _first_ core in this pkg * online. So, initialize per-pkg data structures and * then bring this core online. */ err = coretemp_device_add(cpu); if (err) return; /* * Check whether pkgtemp support is available. * If so, add interfaces for pkgtemp. */ if (cpu_has(c, X86_FEATURE_PTS)) coretemp_add_core(cpu, 1); } /* * Physical CPU device already exists. * So, just add interfaces for this core. */ coretemp_add_core(cpu, 0); } static void __cpuinit put_core_offline(unsigned int cpu) { int i, indx; struct platform_data *pdata; struct platform_device *pdev = coretemp_get_pdev(cpu); /* If the physical CPU device does not exist, just return */ if (!pdev) return; pdata = platform_get_drvdata(pdev); indx = TO_ATTR_NO(cpu); if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu) coretemp_remove_core(pdata, &pdev->dev, indx); |
f4e0bcf06 hwmon: (coretemp)... |
698 |
/* |
6777b9e47 hwmon: (coretemp)... |
699 700 701 702 |
* If a HT sibling of a core is taken offline, but another HT sibling * of the same core is still online, register the alternate sibling. * This ensures that exactly one set of attributes is provided as long * as at least one HT sibling of a core is online. |
f4e0bcf06 hwmon: (coretemp)... |
703 |
*/ |
bb74e8ca3 hwmon: (coretemp)... |
704 |
for_each_sibling(i, cpu) { |
199e0de7f hwmon: (coretemp)... |
705 706 |
if (i != cpu) { get_core_online(i); |
f4e0bcf06 hwmon: (coretemp)... |
707 708 709 710 711 |
/* * Display temperature sensor data for one HT sibling * per core only, so abort the loop after one such * sibling has been found. */ |
199e0de7f hwmon: (coretemp)... |
712 713 714 715 716 717 718 719 720 721 722 723 |
break; } } /* * If all cores in this pkg are offline, remove the device. * coretemp_device_remove calls unregister_platform_device, * which in turn calls coretemp_remove. This removes the * pkgtemp entry and does other clean ups. */ if (!is_any_core_online(pdata)) coretemp_device_remove(cpu); } |
ba7c1927a hwmon: (coretemp)... |
724 |
static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, |
bebe46782 hwmon: New corete... |
725 726 727 728 729 730 |
unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long) hcpu; switch (action) { case CPU_ONLINE: |
561d9a969 HWMON: coretemp, ... |
731 |
case CPU_DOWN_FAILED: |
199e0de7f hwmon: (coretemp)... |
732 |
get_core_online(cpu); |
bebe46782 hwmon: New corete... |
733 |
break; |
561d9a969 HWMON: coretemp, ... |
734 |
case CPU_DOWN_PREPARE: |
199e0de7f hwmon: (coretemp)... |
735 |
put_core_offline(cpu); |
bebe46782 hwmon: New corete... |
736 737 738 739 |
break; } return NOTIFY_OK; } |
ba7c1927a hwmon: (coretemp)... |
740 |
static struct notifier_block coretemp_cpu_notifier __refdata = { |
bebe46782 hwmon: New corete... |
741 742 |
.notifier_call = coretemp_cpu_callback, }; |
bebe46782 hwmon: New corete... |
743 744 745 746 |
static int __init coretemp_init(void) { int i, err = -ENODEV; |
bebe46782 hwmon: New corete... |
747 |
|
bebe46782 hwmon: New corete... |
748 |
/* quick check if we run Intel */ |
92cb7612a x86: convert cpui... |
749 |
if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) |
bebe46782 hwmon: New corete... |
750 751 752 753 754 |
goto exit; err = platform_driver_register(&coretemp_driver); if (err) goto exit; |
a46590533 x86/hwmon: fix in... |
755 |
for_each_online_cpu(i) |
199e0de7f hwmon: (coretemp)... |
756 |
get_core_online(i); |
89a3fd35b x86/hwmon: fix mo... |
757 758 |
#ifndef CONFIG_HOTPLUG_CPU |
bebe46782 hwmon: New corete... |
759 760 761 762 |
if (list_empty(&pdev_list)) { err = -ENODEV; goto exit_driver_unreg; } |
89a3fd35b x86/hwmon: fix mo... |
763 |
#endif |
bebe46782 hwmon: New corete... |
764 |
|
bebe46782 hwmon: New corete... |
765 |
register_hotcpu_notifier(&coretemp_cpu_notifier); |
bebe46782 hwmon: New corete... |
766 |
return 0; |
0dca94bae hwmon: coretemp: ... |
767 |
#ifndef CONFIG_HOTPLUG_CPU |
89a3fd35b x86/hwmon: fix mo... |
768 |
exit_driver_unreg: |
bebe46782 hwmon: New corete... |
769 |
platform_driver_unregister(&coretemp_driver); |
0dca94bae hwmon: coretemp: ... |
770 |
#endif |
bebe46782 hwmon: New corete... |
771 772 773 774 775 776 777 |
exit: return err; } static void __exit coretemp_exit(void) { struct pdev_entry *p, *n; |
17c10d61c hwmon: ({core, pk... |
778 |
|
bebe46782 hwmon: New corete... |
779 |
unregister_hotcpu_notifier(&coretemp_cpu_notifier); |
bebe46782 hwmon: New corete... |
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { platform_device_unregister(p->pdev); list_del(&p->list); kfree(p); } mutex_unlock(&pdev_list_mutex); platform_driver_unregister(&coretemp_driver); } MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>"); MODULE_DESCRIPTION("Intel Core temperature monitor"); MODULE_LICENSE("GPL"); module_init(coretemp_init) module_exit(coretemp_exit) |