Blame view
drivers/hwmon/coretemp.c
20.2 KB
935912c53 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
bebe46782 hwmon: New corete... |
2 3 4 5 6 7 |
/* * coretemp.c - Linux kernel module for hardware monitoring * * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz> * * Inspired from many hwmon drivers |
bebe46782 hwmon: New corete... |
8 |
*/ |
f8bb89256 hwmon: (coretemp)... |
9 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
bebe46782 hwmon: New corete... |
10 |
#include <linux/module.h> |
bebe46782 hwmon: New corete... |
11 12 13 14 15 16 17 18 19 20 21 |
#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> |
4cc452758 hwmon: (coretemp)... |
22 |
#include <linux/smp.h> |
a45a8c857 hwmon: (coretemp)... |
23 |
#include <linux/moduleparam.h> |
14513ee69 hwmon: (coretemp)... |
24 |
#include <linux/pci.h> |
bebe46782 hwmon: New corete... |
25 26 |
#include <asm/msr.h> #include <asm/processor.h> |
9b38096fd HWMON: Convert co... |
27 |
#include <asm/cpu_device_id.h> |
bebe46782 hwmon: New corete... |
28 29 |
#define DRVNAME "coretemp" |
a45a8c857 hwmon: (coretemp)... |
30 31 32 33 34 35 36 |
/* * 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"); |
723f57343 hwmon: (coretemp)... |
37 |
#define PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */ |
199e0de7f hwmon: (coretemp)... |
38 |
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ |
cc904f9cf hwmon: (coretemp)... |
39 |
#define NUM_REAL_CORES 128 /* Number of Real cores per cpu */ |
3f9aec761 hwmon: (coretemp)... |
40 |
#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */ |
c814a4c7c hwmon: (coretemp)... |
41 |
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
f4af6fd6e hwmon: (coretemp)... |
42 |
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) |
199e0de7f hwmon: (coretemp)... |
43 |
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) |
780affe0e hwmon: (coretemp)... |
44 |
#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id) |
141168c36 x86: Simplify cod... |
45 46 47 |
#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) #ifdef CONFIG_SMP |
19a34eea4 coretemp: Replace... |
48 49 |
#define for_each_sibling(i, cpu) \ for_each_cpu(i, topology_sibling_cpumask(cpu)) |
199e0de7f hwmon: (coretemp)... |
50 |
#else |
bb74e8ca3 hwmon: (coretemp)... |
51 |
#define for_each_sibling(i, cpu) for (i = 0; false; ) |
199e0de7f hwmon: (coretemp)... |
52 |
#endif |
bebe46782 hwmon: New corete... |
53 54 |
/* |
199e0de7f hwmon: (coretemp)... |
55 56 57 58 59 60 61 |
* 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)... |
62 |
* @attr_size: Total number of pre-core attrs displayed in the sysfs. |
199e0de7f hwmon: (coretemp)... |
63 64 65 |
* @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... |
66 |
*/ |
199e0de7f hwmon: (coretemp)... |
67 |
struct temp_data { |
bebe46782 hwmon: New corete... |
68 |
int temp; |
6369a2887 hwmon: (coretemp)... |
69 |
int ttarget; |
199e0de7f hwmon: (coretemp)... |
70 71 72 73 74 |
int tjmax; unsigned long last_updated; unsigned int cpu; u32 cpu_core_id; u32 status_reg; |
c814a4c7c hwmon: (coretemp)... |
75 |
int attr_size; |
199e0de7f hwmon: (coretemp)... |
76 77 |
bool is_pkg_data; bool valid; |
c814a4c7c hwmon: (coretemp)... |
78 79 |
struct sensor_device_attribute sd_attrs[TOTAL_ATTRS]; char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH]; |
1075305de hwmon: (coretemp)... |
80 81 |
struct attribute *attrs[TOTAL_ATTRS + 1]; struct attribute_group attr_group; |
199e0de7f hwmon: (coretemp)... |
82 |
struct mutex update_lock; |
bebe46782 hwmon: New corete... |
83 |
}; |
199e0de7f hwmon: (coretemp)... |
84 85 |
/* Platform Data per Physical CPU */ struct platform_data { |
e1b370b64 hwmon: (coretemp)... |
86 |
struct device *hwmon_dev; |
712668460 hwmon: (coretemp)... |
87 |
u16 pkg_id; |
e1b370b64 hwmon: (coretemp)... |
88 89 |
struct cpumask cpumask; struct temp_data *core_data[MAX_CORE_DATA]; |
199e0de7f hwmon: (coretemp)... |
90 91 |
struct device_attribute name_attr; }; |
bebe46782 hwmon: New corete... |
92 |
|
835896a59 hwmon/coretemp: C... |
93 94 95 96 |
/* Keep track of how many zone pointers we allocated in init() */ static int max_zones __read_mostly; /* Array of zone pointers. Serialized by cpu hotplug lock */ static struct platform_device **zone_devices; |
199e0de7f hwmon: (coretemp)... |
97 |
|
199e0de7f hwmon: (coretemp)... |
98 99 |
static ssize_t show_label(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
100 |
{ |
bebe46782 hwmon: New corete... |
101 |
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
199e0de7f hwmon: (coretemp)... |
102 103 104 105 |
struct platform_data *pdata = dev_get_drvdata(dev); struct temp_data *tdata = pdata->core_data[attr->index]; if (tdata->is_pkg_data) |
712668460 hwmon: (coretemp)... |
106 107 |
return sprintf(buf, "Package id %u ", pdata->pkg_id); |
bebe46782 hwmon: New corete... |
108 |
|
199e0de7f hwmon: (coretemp)... |
109 110 |
return sprintf(buf, "Core %u ", tdata->cpu_core_id); |
bebe46782 hwmon: New corete... |
111 |
} |
199e0de7f hwmon: (coretemp)... |
112 113 |
static ssize_t show_crit_alarm(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
114 |
{ |
199e0de7f hwmon: (coretemp)... |
115 116 117 118 |
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]; |
723f57343 hwmon: (coretemp)... |
119 |
mutex_lock(&tdata->update_lock); |
199e0de7f hwmon: (coretemp)... |
120 |
rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); |
723f57343 hwmon: (coretemp)... |
121 |
mutex_unlock(&tdata->update_lock); |
199e0de7f hwmon: (coretemp)... |
122 123 124 |
return sprintf(buf, "%d ", (eax >> 5) & 1); |
bebe46782 hwmon: New corete... |
125 |
} |
199e0de7f hwmon: (coretemp)... |
126 127 |
static ssize_t show_tjmax(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
128 129 |
{ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
199e0de7f hwmon: (coretemp)... |
130 |
struct platform_data *pdata = dev_get_drvdata(dev); |
bebe46782 hwmon: New corete... |
131 |
|
199e0de7f hwmon: (coretemp)... |
132 133 |
return sprintf(buf, "%d ", pdata->core_data[attr->index]->tjmax); |
bebe46782 hwmon: New corete... |
134 |
} |
199e0de7f hwmon: (coretemp)... |
135 136 137 138 139 |
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... |
140 |
|
199e0de7f hwmon: (coretemp)... |
141 142 143 |
return sprintf(buf, "%d ", pdata->core_data[attr->index]->ttarget); } |
bebe46782 hwmon: New corete... |
144 |
|
199e0de7f hwmon: (coretemp)... |
145 146 |
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) |
bebe46782 hwmon: New corete... |
147 |
{ |
199e0de7f hwmon: (coretemp)... |
148 149 150 151 |
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... |
152 |
|
199e0de7f hwmon: (coretemp)... |
153 |
mutex_lock(&tdata->update_lock); |
bebe46782 hwmon: New corete... |
154 |
|
199e0de7f hwmon: (coretemp)... |
155 156 157 |
/* 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); |
bf6ea084e hwmon: (coretemp)... |
158 159 160 161 162 163 164 165 |
/* * Ignore the valid bit. In all observed cases the register * value is either low or zero if the valid bit is 0. * Return it instead of reporting an error which doesn't * really help at all. */ tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; tdata->valid = 1; |
199e0de7f hwmon: (coretemp)... |
166 |
tdata->last_updated = jiffies; |
bebe46782 hwmon: New corete... |
167 |
} |
199e0de7f hwmon: (coretemp)... |
168 |
mutex_unlock(&tdata->update_lock); |
bf6ea084e hwmon: (coretemp)... |
169 170 |
return sprintf(buf, "%d ", tdata->temp); |
bebe46782 hwmon: New corete... |
171 |
} |
14513ee69 hwmon: (coretemp)... |
172 173 174 175 176 177 |
struct tjmax_pci { unsigned int device; int tjmax; }; static const struct tjmax_pci tjmax_pci_table[] = { |
347c16cfd hwmon: (coretemp)... |
178 |
{ 0x0708, 110000 }, /* CE41x0 (Sodaville ) */ |
14513ee69 hwmon: (coretemp)... |
179 180 181 182 |
{ 0x0c72, 102000 }, /* Atom S1240 (Centerton) */ { 0x0c73, 95000 }, /* Atom S1220 (Centerton) */ { 0x0c75, 95000 }, /* Atom S1260 (Centerton) */ }; |
41e58a1f2 hwmon: (coretemp)... |
183 184 185 186 |
struct tjmax { char const *id; int tjmax; }; |
d23e2ae1a hwmon: delete __c... |
187 |
static const struct tjmax tjmax_table[] = { |
1102dcab8 hwmon: (coretemp)... |
188 189 |
{ "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ |
41e58a1f2 hwmon: (coretemp)... |
190 |
}; |
2fa5222ef hwmon: (coretemp)... |
191 192 193 194 195 196 197 |
struct tjmax_model { u8 model; u8 mask; int tjmax; }; #define ANY 0xff |
d23e2ae1a hwmon: delete __c... |
198 |
static const struct tjmax_model tjmax_model_table[] = { |
9e3970fba hwmon: (coretemp)... |
199 |
{ 0x1c, 10, 100000 }, /* D4xx, K4xx, N4xx, D5xx, K5xx, N5xx */ |
2fa5222ef hwmon: (coretemp)... |
200 201 202 203 204 205 206 207 208 |
{ 0x1c, ANY, 90000 }, /* Z5xx, N2xx, possibly others * Note: Also matches 230 and 330, * which are covered by tjmax_table */ { 0x26, ANY, 90000 }, /* Atom Tunnel Creek (Exx), Lincroft (Z6xx) * Note: TjMax for E6xxT is 110C, but CPU type * is undetectable by software */ { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */ |
14513ee69 hwmon: (coretemp)... |
209 210 211 212 213 |
{ 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z27x0) */ { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) * Also matches S12x0 (stepping 9), covered by * PCI table */ |
2fa5222ef hwmon: (coretemp)... |
214 |
}; |
d23e2ae1a hwmon: delete __c... |
215 |
static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) |
118a88718 hwmon: (coretemp)... |
216 217 218 219 |
{ /* The 100C is default for both mobile and non mobile CPUs */ int tjmax = 100000; |
eccfed422 hwmon: (coretemp)... |
220 |
int tjmax_ee = 85000; |
708a62bcd hwmon: (coretemp)... |
221 |
int usemsr_ee = 1; |
118a88718 hwmon: (coretemp)... |
222 223 |
int err; u32 eax, edx; |
41e58a1f2 hwmon: (coretemp)... |
224 |
int i; |
b9ccff233 hwmon: (coretemp)... |
225 226 |
u16 devfn = PCI_DEVFN(0, 0); struct pci_dev *host_bridge = pci_get_domain_bus_and_slot(0, 0, devfn); |
14513ee69 hwmon: (coretemp)... |
227 228 229 230 231 232 233 234 235 236 237 238 |
/* * Explicit tjmax table entries override heuristics. * First try PCI host bridge IDs, followed by model ID strings * and model/stepping information. */ if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) { for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) { if (host_bridge->device == tjmax_pci_table[i].device) return tjmax_pci_table[i].tjmax; } } |
41e58a1f2 hwmon: (coretemp)... |
239 |
|
41e58a1f2 hwmon: (coretemp)... |
240 241 242 243 |
for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) { if (strstr(c->x86_model_id, tjmax_table[i].id)) return tjmax_table[i].tjmax; } |
118a88718 hwmon: (coretemp)... |
244 |
|
2fa5222ef hwmon: (coretemp)... |
245 246 247 |
for (i = 0; i < ARRAY_SIZE(tjmax_model_table); i++) { const struct tjmax_model *tm = &tjmax_model_table[i]; if (c->x86_model == tm->model && |
b399151cb x86/cpu: Rename c... |
248 |
(tm->mask == ANY || c->x86_stepping == tm->mask)) |
2fa5222ef hwmon: (coretemp)... |
249 |
return tm->tjmax; |
72cbdddcc hwmon: (coretemp)... |
250 |
} |
1fe63ab47 hwmon: (coretemp)... |
251 |
|
72cbdddcc hwmon: (coretemp)... |
252 |
/* Early chips have no MSR for TjMax */ |
1fe63ab47 hwmon: (coretemp)... |
253 |
|
b399151cb x86/cpu: Rename c... |
254 |
if (c->x86_model == 0xf && c->x86_stepping < 4) |
5592906f8 hwmon: (coretemp)... |
255 |
usemsr_ee = 0; |
708a62bcd hwmon: (coretemp)... |
256 |
|
4cc452758 hwmon: (coretemp)... |
257 |
if (c->x86_model > 0xe && usemsr_ee) { |
eccfed422 hwmon: (coretemp)... |
258 |
u8 platform_id; |
118a88718 hwmon: (coretemp)... |
259 |
|
4cc452758 hwmon: (coretemp)... |
260 261 262 263 264 |
/* * 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)... |
265 266 267 268 269 270 |
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)... |
271 |
usemsr_ee = 0; |
eccfed422 hwmon: (coretemp)... |
272 |
} else if (c->x86_model < 0x17 && !(eax & 0x10000000)) { |
4cc452758 hwmon: (coretemp)... |
273 274 275 276 277 |
/* * 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)... |
278 |
usemsr_ee = 0; |
eccfed422 hwmon: (coretemp)... |
279 280 281 |
} else { /* Platform ID bits 52:50 (EDX starts at bit 32) */ platform_id = (edx >> 18) & 0x7; |
4cc452758 hwmon: (coretemp)... |
282 283 284 285 286 287 288 289 290 291 |
/* * 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)... |
292 293 294 |
tjmax_ee = 90000; tjmax = 105000; } |
118a88718 hwmon: (coretemp)... |
295 296 |
} } |
708a62bcd hwmon: (coretemp)... |
297 |
if (usemsr_ee) { |
118a88718 hwmon: (coretemp)... |
298 299 300 301 |
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)... |
302 303 |
" at default "); |
118a88718 hwmon: (coretemp)... |
304 |
} else if (eax & 0x40000000) { |
eccfed422 hwmon: (coretemp)... |
305 |
tjmax = tjmax_ee; |
118a88718 hwmon: (coretemp)... |
306 |
} |
708a62bcd hwmon: (coretemp)... |
307 |
} else if (tjmax == 100000) { |
4cc452758 hwmon: (coretemp)... |
308 309 310 311 |
/* * If we don't use msr EE it means we are desktop CPU * (with exeception of Atom) */ |
118a88718 hwmon: (coretemp)... |
312 313 314 315 316 317 |
dev_warn(dev, "Using relative temperature scale! "); } return tjmax; } |
1c2faa224 hwmon: (coretemp)... |
318 319 320 321 322 323 324 325 326 327 328 |
static bool cpu_has_tjmax(struct cpuinfo_x86 *c) { u8 model = c->x86_model; return model > 0xe && model != 0x1c && model != 0x26 && model != 0x27 && model != 0x35 && model != 0x36; } |
d23e2ae1a hwmon: delete __c... |
329 |
static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) |
a321cedb1 drivers/hwmon/cor... |
330 |
{ |
a321cedb1 drivers/hwmon/cor... |
331 332 333 |
int err; u32 eax, edx; u32 val; |
4cc452758 hwmon: (coretemp)... |
334 335 336 337 |
/* * A new feature of current Intel(R) processors, the * IA32_TEMPERATURE_TARGET contains the TjMax value */ |
a321cedb1 drivers/hwmon/cor... |
338 339 |
err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); if (err) { |
1c2faa224 hwmon: (coretemp)... |
340 |
if (cpu_has_tjmax(c)) |
6bf9e9b09 hwmon: (coretemp)... |
341 342 |
dev_warn(dev, "Unable to read TjMax from CPU %u ", id); |
a321cedb1 drivers/hwmon/cor... |
343 |
} else { |
c0940e95f Revert "hwmon: (c... |
344 |
val = (eax >> 16) & 0xff; |
a321cedb1 drivers/hwmon/cor... |
345 346 347 348 |
/* * If the TjMax is not plausible, an assumption * will be used */ |
c0940e95f Revert "hwmon: (c... |
349 |
if (val) { |
6bf9e9b09 hwmon: (coretemp)... |
350 351 |
dev_dbg(dev, "TjMax is %d degrees C ", val); |
a321cedb1 drivers/hwmon/cor... |
352 353 354 |
return val * 1000; } } |
a45a8c857 hwmon: (coretemp)... |
355 356 357 358 359 360 |
if (force_tjmax) { dev_notice(dev, "TjMax forced to %d degrees C by user ", force_tjmax); return force_tjmax * 1000; } |
a321cedb1 drivers/hwmon/cor... |
361 362 |
/* * An assumption is made for early CPUs and unreadable MSR. |
4f5f71a7a hwmon: (coretemp)... |
363 |
* NOTE: the calculated value may not be correct. |
a321cedb1 drivers/hwmon/cor... |
364 |
*/ |
4f5f71a7a hwmon: (coretemp)... |
365 |
return adjust_tjmax(c, id, dev); |
a321cedb1 drivers/hwmon/cor... |
366 |
} |
d23e2ae1a hwmon: delete __c... |
367 368 |
static int create_core_attrs(struct temp_data *tdata, struct device *dev, int attr_no) |
199e0de7f hwmon: (coretemp)... |
369 |
{ |
1075305de hwmon: (coretemp)... |
370 |
int i; |
e3204ed3a hwmon: (coretemp)... |
371 |
static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, |
199e0de7f hwmon: (coretemp)... |
372 |
struct device_attribute *devattr, char *buf) = { |
c814a4c7c hwmon: (coretemp)... |
373 |
show_label, show_crit_alarm, show_temp, show_tjmax, |
f4af6fd6e hwmon: (coretemp)... |
374 |
show_ttarget }; |
1055b5f90 hwmon: (coretemp)... |
375 376 377 |
static const char *const suffixes[TOTAL_ATTRS] = { "label", "crit_alarm", "input", "crit", "max" }; |
199e0de7f hwmon: (coretemp)... |
378 |
|
c814a4c7c hwmon: (coretemp)... |
379 |
for (i = 0; i < tdata->attr_size; i++) { |
1055b5f90 hwmon: (coretemp)... |
380 381 |
snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, "temp%d_%s", attr_no, suffixes[i]); |
4258781ac hwmon: (coretemp)... |
382 |
sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); |
199e0de7f hwmon: (coretemp)... |
383 |
tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; |
0cd709d0d hwmon: (coretemp)... |
384 |
tdata->sd_attrs[i].dev_attr.attr.mode = 0444; |
199e0de7f hwmon: (coretemp)... |
385 |
tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; |
199e0de7f hwmon: (coretemp)... |
386 |
tdata->sd_attrs[i].index = attr_no; |
1075305de hwmon: (coretemp)... |
387 |
tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr; |
bebe46782 hwmon: New corete... |
388 |
} |
1075305de hwmon: (coretemp)... |
389 390 |
tdata->attr_group.attrs = tdata->attrs; return sysfs_create_group(&dev->kobj, &tdata->attr_group); |
199e0de7f hwmon: (coretemp)... |
391 |
} |
199e0de7f hwmon: (coretemp)... |
392 |
|
d23e2ae1a hwmon: delete __c... |
393 |
static int chk_ucode_version(unsigned int cpu) |
199e0de7f hwmon: (coretemp)... |
394 |
{ |
0eb9782ad hwmon: (coretemp)... |
395 |
struct cpuinfo_x86 *c = &cpu_data(cpu); |
67f363b1f hwmon/coretemp: A... |
396 |
|
199e0de7f hwmon: (coretemp)... |
397 398 399 400 401 |
/* * 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). */ |
b399151cb x86/cpu: Rename c... |
402 |
if (c->x86_model == 0xe && c->x86_stepping < 0xc && c->microcode < 0x39) { |
b55f37572 hwmon: Fix checkp... |
403 404 |
pr_err("Errata AE18 not fixed, update BIOS or microcode of the CPU! "); |
ca8bc8dc0 coretemp: Get mic... |
405 |
return -ENODEV; |
67f363b1f hwmon/coretemp: A... |
406 |
} |
199e0de7f hwmon: (coretemp)... |
407 408 |
return 0; } |
d23e2ae1a hwmon: delete __c... |
409 |
static struct platform_device *coretemp_get_pdev(unsigned int cpu) |
199e0de7f hwmon: (coretemp)... |
410 |
{ |
835896a59 hwmon/coretemp: C... |
411 |
int id = topology_logical_die_id(cpu); |
199e0de7f hwmon: (coretemp)... |
412 |
|
835896a59 hwmon/coretemp: C... |
413 414 |
if (id >= 0 && id < max_zones) return zone_devices[id]; |
199e0de7f hwmon: (coretemp)... |
415 416 |
return NULL; } |
d23e2ae1a hwmon: delete __c... |
417 |
static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) |
199e0de7f hwmon: (coretemp)... |
418 419 420 421 422 423 424 425 426 427 428 429 |
{ 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)... |
430 |
tdata->attr_size = MAX_CORE_ATTRS; |
199e0de7f hwmon: (coretemp)... |
431 432 433 |
mutex_init(&tdata->update_lock); return tdata; } |
67f363b1f hwmon/coretemp: A... |
434 |
|
d23e2ae1a hwmon: delete __c... |
435 436 |
static int create_core_data(struct platform_device *pdev, unsigned int cpu, int pkg_flag) |
199e0de7f hwmon: (coretemp)... |
437 438 |
{ struct temp_data *tdata; |
2f1c3db0a hwmon: (coretemp)... |
439 |
struct platform_data *pdata = platform_get_drvdata(pdev); |
199e0de7f hwmon: (coretemp)... |
440 441 442 |
struct cpuinfo_x86 *c = &cpu_data(cpu); u32 eax, edx; int err, attr_no; |
bebe46782 hwmon: New corete... |
443 |
|
a321cedb1 drivers/hwmon/cor... |
444 |
/* |
199e0de7f hwmon: (coretemp)... |
445 446 447 448 |
* 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... |
449 |
*/ |
723f57343 hwmon: (coretemp)... |
450 |
attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu); |
6369a2887 hwmon: (coretemp)... |
451 |
|
199e0de7f hwmon: (coretemp)... |
452 453 |
if (attr_no > MAX_CORE_DATA - 1) return -ERANGE; |
199e0de7f hwmon: (coretemp)... |
454 455 456 |
tdata = init_temp_data(cpu, pkg_flag); if (!tdata) return -ENOMEM; |
bebe46782 hwmon: New corete... |
457 |
|
199e0de7f hwmon: (coretemp)... |
458 459 460 461 462 463 |
/* 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)... |
464 |
tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); |
199e0de7f hwmon: (coretemp)... |
465 |
|
c814a4c7c hwmon: (coretemp)... |
466 |
/* |
f4af6fd6e hwmon: (coretemp)... |
467 468 469 |
* 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)... |
470 |
*/ |
f4af6fd6e hwmon: (coretemp)... |
471 472 473 474 475 476 477 478 |
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)... |
479 |
} |
199e0de7f hwmon: (coretemp)... |
480 481 482 |
pdata->core_data[attr_no] = tdata; /* Create sysfs interfaces */ |
d72d19c26 hwmon: (coretemp)... |
483 |
err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no); |
199e0de7f hwmon: (coretemp)... |
484 485 |
if (err) goto exit_free; |
bebe46782 hwmon: New corete... |
486 487 |
return 0; |
199e0de7f hwmon: (coretemp)... |
488 |
exit_free: |
20ecb499f hwmon: (coretemp)... |
489 |
pdata->core_data[attr_no] = NULL; |
199e0de7f hwmon: (coretemp)... |
490 491 492 |
kfree(tdata); return err; } |
4b138cf73 hwmon: (coretemp)... |
493 494 |
static void coretemp_add_core(struct platform_device *pdev, unsigned int cpu, int pkg_flag) |
199e0de7f hwmon: (coretemp)... |
495 |
{ |
4b138cf73 hwmon: (coretemp)... |
496 |
if (create_core_data(pdev, cpu, pkg_flag)) |
199e0de7f hwmon: (coretemp)... |
497 498 499 |
dev_err(&pdev->dev, "Adding Core %u failed ", cpu); } |
4b138cf73 hwmon: (coretemp)... |
500 |
static void coretemp_remove_core(struct platform_data *pdata, int indx) |
199e0de7f hwmon: (coretemp)... |
501 |
{ |
199e0de7f hwmon: (coretemp)... |
502 503 504 |
struct temp_data *tdata = pdata->core_data[indx]; /* Remove the sysfs attributes */ |
d72d19c26 hwmon: (coretemp)... |
505 |
sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group); |
199e0de7f hwmon: (coretemp)... |
506 507 508 509 |
kfree(pdata->core_data[indx]); pdata->core_data[indx] = NULL; } |
6c931ae1c hwmon: remove use... |
510 |
static int coretemp_probe(struct platform_device *pdev) |
199e0de7f hwmon: (coretemp)... |
511 |
{ |
c503a811e hwmon: (coretemp)... |
512 |
struct device *dev = &pdev->dev; |
199e0de7f hwmon: (coretemp)... |
513 |
struct platform_data *pdata; |
bebe46782 hwmon: New corete... |
514 |
|
835896a59 hwmon/coretemp: C... |
515 |
/* Initialize the per-zone data structures */ |
c503a811e hwmon: (coretemp)... |
516 |
pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL); |
199e0de7f hwmon: (coretemp)... |
517 518 |
if (!pdata) return -ENOMEM; |
712668460 hwmon: (coretemp)... |
519 |
pdata->pkg_id = pdev->id; |
199e0de7f hwmon: (coretemp)... |
520 |
platform_set_drvdata(pdev, pdata); |
d72d19c26 hwmon: (coretemp)... |
521 522 523 |
pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, pdata, NULL); return PTR_ERR_OR_ZERO(pdata->hwmon_dev); |
bebe46782 hwmon: New corete... |
524 |
} |
281dfd0b6 hwmon: remove use... |
525 |
static int coretemp_remove(struct platform_device *pdev) |
bebe46782 hwmon: New corete... |
526 |
{ |
199e0de7f hwmon: (coretemp)... |
527 528 |
struct platform_data *pdata = platform_get_drvdata(pdev); int i; |
bebe46782 hwmon: New corete... |
529 |
|
199e0de7f hwmon: (coretemp)... |
530 531 |
for (i = MAX_CORE_DATA - 1; i >= 0; --i) if (pdata->core_data[i]) |
d72d19c26 hwmon: (coretemp)... |
532 |
coretemp_remove_core(pdata, i); |
199e0de7f hwmon: (coretemp)... |
533 |
|
bebe46782 hwmon: New corete... |
534 535 536 537 538 |
return 0; } static struct platform_driver coretemp_driver = { .driver = { |
bebe46782 hwmon: New corete... |
539 540 541 |
.name = DRVNAME, }, .probe = coretemp_probe, |
9e5e9b7a9 hwmon: remove use... |
542 |
.remove = coretemp_remove, |
bebe46782 hwmon: New corete... |
543 |
}; |
712668460 hwmon: (coretemp)... |
544 |
static struct platform_device *coretemp_device_add(unsigned int cpu) |
bebe46782 hwmon: New corete... |
545 |
{ |
835896a59 hwmon/coretemp: C... |
546 |
int err, zoneid = topology_logical_die_id(cpu); |
bebe46782 hwmon: New corete... |
547 |
struct platform_device *pdev; |
d883b9f09 hwmon: (coretemp)... |
548 |
|
835896a59 hwmon/coretemp: C... |
549 |
if (zoneid < 0) |
712668460 hwmon: (coretemp)... |
550 |
return ERR_PTR(-ENOMEM); |
d883b9f09 hwmon: (coretemp)... |
551 |
|
835896a59 hwmon/coretemp: C... |
552 |
pdev = platform_device_alloc(DRVNAME, zoneid); |
712668460 hwmon: (coretemp)... |
553 554 |
if (!pdev) return ERR_PTR(-ENOMEM); |
bebe46782 hwmon: New corete... |
555 556 557 |
err = platform_device_add(pdev); if (err) { |
712668460 hwmon: (coretemp)... |
558 559 |
platform_device_put(pdev); return ERR_PTR(err); |
bebe46782 hwmon: New corete... |
560 |
} |
835896a59 hwmon/coretemp: C... |
561 |
zone_devices[zoneid] = pdev; |
712668460 hwmon: (coretemp)... |
562 |
return pdev; |
bebe46782 hwmon: New corete... |
563 |
} |
e00ca5df3 hwmon: (coretemp)... |
564 |
static int coretemp_cpu_online(unsigned int cpu) |
199e0de7f hwmon: (coretemp)... |
565 |
{ |
199e0de7f hwmon: (coretemp)... |
566 |
struct platform_device *pdev = coretemp_get_pdev(cpu); |
e1b370b64 hwmon: (coretemp)... |
567 568 |
struct cpuinfo_x86 *c = &cpu_data(cpu); struct platform_data *pdata; |
199e0de7f hwmon: (coretemp)... |
569 570 |
/* |
90b4f30b6 hwmon: (coretemp)... |
571 572 573 574 575 576 577 |
* Don't execute this on resume as the offline callback did * not get executed on suspend. */ if (cpuhp_tasks_frozen) return 0; /* |
199e0de7f hwmon: (coretemp)... |
578 579 580 581 |
* 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. */ |
4ad334113 x86, cpufeature: ... |
582 |
if (!cpu_has(c, X86_FEATURE_DTHERM)) |
2195c31b1 hwmon: (coretemp)... |
583 |
return -ENODEV; |
199e0de7f hwmon: (coretemp)... |
584 585 |
if (!pdev) { |
0eb9782ad hwmon: (coretemp)... |
586 587 |
/* Check the microcode version of the CPU */ if (chk_ucode_version(cpu)) |
2195c31b1 hwmon: (coretemp)... |
588 |
return -EINVAL; |
0eb9782ad hwmon: (coretemp)... |
589 |
|
199e0de7f hwmon: (coretemp)... |
590 591 592 593 594 595 |
/* * 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. */ |
712668460 hwmon: (coretemp)... |
596 597 598 |
pdev = coretemp_device_add(cpu); if (IS_ERR(pdev)) return PTR_ERR(pdev); |
e1b370b64 hwmon: (coretemp)... |
599 |
|
199e0de7f hwmon: (coretemp)... |
600 601 602 603 604 |
/* * Check whether pkgtemp support is available. * If so, add interfaces for pkgtemp. */ if (cpu_has(c, X86_FEATURE_PTS)) |
4b138cf73 hwmon: (coretemp)... |
605 |
coretemp_add_core(pdev, cpu, 1); |
199e0de7f hwmon: (coretemp)... |
606 |
} |
e1b370b64 hwmon: (coretemp)... |
607 608 |
pdata = platform_get_drvdata(pdev); |
199e0de7f hwmon: (coretemp)... |
609 |
/* |
e1b370b64 hwmon: (coretemp)... |
610 611 |
* Check whether a thread sibling is already online. If not add the * interface for this CPU core. |
199e0de7f hwmon: (coretemp)... |
612 |
*/ |
e1b370b64 hwmon: (coretemp)... |
613 |
if (!cpumask_intersects(&pdata->cpumask, topology_sibling_cpumask(cpu))) |
4b138cf73 hwmon: (coretemp)... |
614 |
coretemp_add_core(pdev, cpu, 0); |
e1b370b64 hwmon: (coretemp)... |
615 616 |
cpumask_set_cpu(cpu, &pdata->cpumask); |
e00ca5df3 hwmon: (coretemp)... |
617 |
return 0; |
199e0de7f hwmon: (coretemp)... |
618 |
} |
e00ca5df3 hwmon: (coretemp)... |
619 |
static int coretemp_cpu_offline(unsigned int cpu) |
199e0de7f hwmon: (coretemp)... |
620 |
{ |
199e0de7f hwmon: (coretemp)... |
621 |
struct platform_device *pdev = coretemp_get_pdev(cpu); |
e1b370b64 hwmon: (coretemp)... |
622 |
struct platform_data *pd; |
723f57343 hwmon: (coretemp)... |
623 |
struct temp_data *tdata; |
e1b370b64 hwmon: (coretemp)... |
624 |
int indx, target; |
199e0de7f hwmon: (coretemp)... |
625 |
|
90b4f30b6 hwmon: (coretemp)... |
626 627 628 629 630 631 |
/* * Don't execute this on suspend as the device remove locks * up the machine. */ if (cpuhp_tasks_frozen) return 0; |
199e0de7f hwmon: (coretemp)... |
632 633 |
/* If the physical CPU device does not exist, just return */ if (!pdev) |
e00ca5df3 hwmon: (coretemp)... |
634 |
return 0; |
199e0de7f hwmon: (coretemp)... |
635 |
|
b70487112 hwmon: (coretemp)... |
636 |
/* The core id is too big, just return */ |
e1b370b64 hwmon: (coretemp)... |
637 |
indx = TO_ATTR_NO(cpu); |
b70487112 hwmon: (coretemp)... |
638 |
if (indx > MAX_CORE_DATA - 1) |
e00ca5df3 hwmon: (coretemp)... |
639 |
return 0; |
b70487112 hwmon: (coretemp)... |
640 |
|
e1b370b64 hwmon: (coretemp)... |
641 642 643 644 |
pd = platform_get_drvdata(pdev); tdata = pd->core_data[indx]; cpumask_clear_cpu(cpu, &pd->cpumask); |
199e0de7f hwmon: (coretemp)... |
645 |
|
f4e0bcf06 hwmon: (coretemp)... |
646 |
/* |
e1b370b64 hwmon: (coretemp)... |
647 648 649 |
* If this is the last thread sibling, remove the CPU core * interface, If there is still a sibling online, transfer the * target cpu of that core interface to it. |
f4e0bcf06 hwmon: (coretemp)... |
650 |
*/ |
e1b370b64 hwmon: (coretemp)... |
651 652 653 654 655 656 657 |
target = cpumask_any_and(&pd->cpumask, topology_sibling_cpumask(cpu)); if (target >= nr_cpu_ids) { coretemp_remove_core(pd, indx); } else if (tdata && tdata->cpu == cpu) { mutex_lock(&tdata->update_lock); tdata->cpu = target; mutex_unlock(&tdata->update_lock); |
199e0de7f hwmon: (coretemp)... |
658 |
} |
e1b370b64 hwmon: (coretemp)... |
659 |
|
199e0de7f hwmon: (coretemp)... |
660 |
/* |
712668460 hwmon: (coretemp)... |
661 662 663 |
* If all cores in this pkg are offline, remove the device. This * will invoke the platform driver remove function, which cleans up * the rest. |
199e0de7f hwmon: (coretemp)... |
664 |
*/ |
e1b370b64 hwmon: (coretemp)... |
665 |
if (cpumask_empty(&pd->cpumask)) { |
835896a59 hwmon/coretemp: C... |
666 |
zone_devices[topology_logical_die_id(cpu)] = NULL; |
712668460 hwmon: (coretemp)... |
667 |
platform_device_unregister(pdev); |
e00ca5df3 hwmon: (coretemp)... |
668 |
return 0; |
723f57343 hwmon: (coretemp)... |
669 |
} |
712668460 hwmon: (coretemp)... |
670 |
|
723f57343 hwmon: (coretemp)... |
671 672 673 674 |
/* * Check whether this core is the target for the package * interface. We need to assign it to some other cpu. */ |
e1b370b64 hwmon: (coretemp)... |
675 |
tdata = pd->core_data[PKG_SYSFS_ATTR_NO]; |
723f57343 hwmon: (coretemp)... |
676 |
if (tdata && tdata->cpu == cpu) { |
e1b370b64 hwmon: (coretemp)... |
677 |
target = cpumask_first(&pd->cpumask); |
723f57343 hwmon: (coretemp)... |
678 679 680 681 |
mutex_lock(&tdata->update_lock); tdata->cpu = target; mutex_unlock(&tdata->update_lock); } |
e00ca5df3 hwmon: (coretemp)... |
682 |
return 0; |
199e0de7f hwmon: (coretemp)... |
683 |
} |
e273bd98c hwmon: struct x86... |
684 |
static const struct x86_cpu_id __initconst coretemp_ids[] = { |
4ad334113 x86, cpufeature: ... |
685 |
{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, |
9b38096fd HWMON: Convert co... |
686 687 688 |
{} }; MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); |
e00ca5df3 hwmon: (coretemp)... |
689 |
static enum cpuhp_state coretemp_hp_online; |
bebe46782 hwmon: New corete... |
690 691 |
static int __init coretemp_init(void) { |
e00ca5df3 hwmon: (coretemp)... |
692 |
int err; |
bebe46782 hwmon: New corete... |
693 |
|
9b38096fd HWMON: Convert co... |
694 695 696 697 698 699 700 |
/* * 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 (!x86_match_cpu(coretemp_ids)) return -ENODEV; |
bebe46782 hwmon: New corete... |
701 |
|
835896a59 hwmon/coretemp: C... |
702 703 |
max_zones = topology_max_packages() * topology_max_die_per_package(); zone_devices = kcalloc(max_zones, sizeof(struct platform_device *), |
712668460 hwmon: (coretemp)... |
704 |
GFP_KERNEL); |
835896a59 hwmon/coretemp: C... |
705 |
if (!zone_devices) |
712668460 hwmon: (coretemp)... |
706 |
return -ENOMEM; |
bebe46782 hwmon: New corete... |
707 708 |
err = platform_driver_register(&coretemp_driver); if (err) |
e027a2dea hwmon (coretemp) ... |
709 |
goto outzone; |
bebe46782 hwmon: New corete... |
710 |
|
e00ca5df3 hwmon: (coretemp)... |
711 712 713 |
err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online", coretemp_cpu_online, coretemp_cpu_offline); if (err < 0) |
2195c31b1 hwmon: (coretemp)... |
714 |
goto outdrv; |
e00ca5df3 hwmon: (coretemp)... |
715 |
coretemp_hp_online = err; |
bebe46782 hwmon: New corete... |
716 |
return 0; |
2195c31b1 hwmon: (coretemp)... |
717 |
outdrv: |
bebe46782 hwmon: New corete... |
718 |
platform_driver_unregister(&coretemp_driver); |
e027a2dea hwmon (coretemp) ... |
719 |
outzone: |
835896a59 hwmon/coretemp: C... |
720 |
kfree(zone_devices); |
bebe46782 hwmon: New corete... |
721 722 |
return err; } |
e00ca5df3 hwmon: (coretemp)... |
723 |
module_init(coretemp_init) |
bebe46782 hwmon: New corete... |
724 725 726 |
static void __exit coretemp_exit(void) { |
e00ca5df3 hwmon: (coretemp)... |
727 |
cpuhp_remove_state(coretemp_hp_online); |
bebe46782 hwmon: New corete... |
728 |
platform_driver_unregister(&coretemp_driver); |
835896a59 hwmon/coretemp: C... |
729 |
kfree(zone_devices); |
bebe46782 hwmon: New corete... |
730 |
} |
e00ca5df3 hwmon: (coretemp)... |
731 |
module_exit(coretemp_exit) |
bebe46782 hwmon: New corete... |
732 733 734 735 |
MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>"); MODULE_DESCRIPTION("Intel Core temperature monitor"); MODULE_LICENSE("GPL"); |