aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-09-20 00:41:16 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-09-21 20:25:18 -0400
commitf4af6fd6e21792ca4deca3d29c113a575594078e (patch)
treebe578a88996c6e95f9d09384412e5f52230aed8c
parenta45a8c8571c0be6a6bd72ae5a14255c26b14b504 (diff)
hwmon: (coretemp) Don't use threshold registers for tempX_max
With commit c814a4c7c4aad795835583344353963a0a673eb0, the meaning of tempX_max was changed. It no longer returns the value of bits 8:15 of MSR_IA32_TEMPERATURE_TARGET, but instead returns the value of CPU threshold register T1. tempX_max_hyst was added to reflect the value of temperature threshold register T0. As it turns out, T0 and T1 are used on some systems, presumably by the BIOS. Also, T0 and T1 don't have a well defined meaning. The thresholds may be used as upper or lower limits, and it is not guaranteed that T0 <= T1. Thus, the new attribute mapping does not reflect the actual usage of the threshold registers. Also, register contents are changed during runtime by an entity other than the hwmon driver, meaning the values cached by the driver do not reflect actual register contents. Revert most of c814a4c7c4aad795835583344353963a0a673eb0 to address the problem. Support for T0 and T1 will be added back in with a separate commit, using new attribute names. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Durgadoss R <durgadoss.r@intel.com> Acked-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--Documentation/hwmon/coretemp7
-rw-r--r--drivers/hwmon/coretemp.c135
2 files changed, 14 insertions, 128 deletions
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp
index 49c0d42dde86..84d46c0c71a3 100644
--- a/Documentation/hwmon/coretemp
+++ b/Documentation/hwmon/coretemp
@@ -35,13 +35,6 @@ the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
35All Sysfs entries are named with their core_id (represented here by 'X'). 35All Sysfs entries are named with their core_id (represented here by 'X').
36tempX_input - Core temperature (in millidegrees Celsius). 36tempX_input - Core temperature (in millidegrees Celsius).
37tempX_max - All cooling devices should be turned on (on Core2). 37tempX_max - All cooling devices should be turned on (on Core2).
38 Initialized with IA32_THERM_INTERRUPT. When the CPU
39 temperature reaches this temperature, an interrupt is
40 generated and tempX_max_alarm is set.
41tempX_max_hyst - If the CPU temperature falls below than temperature,
42 an interrupt is generated and tempX_max_alarm is reset.
43tempX_max_alarm - Set if the temperature reaches or exceeds tempX_max.
44 Reset if the temperature drops to or below tempX_max_hyst.
45tempX_crit - Maximum junction temperature (in millidegrees Celsius). 38tempX_crit - Maximum junction temperature (in millidegrees Celsius).
46tempX_crit_alarm - Set when Out-of-spec bit is set, never clears. 39tempX_crit_alarm - Set when Out-of-spec bit is set, never clears.
47 Correct CPU operation is no longer guaranteed. 40 Correct CPU operation is no longer guaranteed.
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 5a41e9dda909..47364151e67a 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -54,8 +54,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
54#define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ 54#define NUM_REAL_CORES 16 /* Number of Real cores per cpu */
55#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ 55#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */
56#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ 56#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
57#define MAX_THRESH_ATTRS 3 /* Maximum no of Threshold attrs */ 57#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
58#define TOTAL_ATTRS (MAX_CORE_ATTRS + MAX_THRESH_ATTRS)
59#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) 58#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
60 59
61#ifdef CONFIG_SMP 60#ifdef CONFIG_SMP
@@ -78,8 +77,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
78 * This value is passed as "id" field to rdmsr/wrmsr functions. 77 * This value is passed as "id" field to rdmsr/wrmsr functions.
79 * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, 78 * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS,
80 * from where the temperature values should be read. 79 * from where the temperature values should be read.
81 * @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT,
82 * from where the thresholds are read.
83 * @attr_size: Total number of pre-core attrs displayed in the sysfs. 80 * @attr_size: Total number of pre-core attrs displayed in the sysfs.
84 * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. 81 * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
85 * Otherwise, temp_data holds coretemp data. 82 * Otherwise, temp_data holds coretemp data.
@@ -88,13 +85,11 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
88struct temp_data { 85struct temp_data {
89 int temp; 86 int temp;
90 int ttarget; 87 int ttarget;
91 int tmin;
92 int tjmax; 88 int tjmax;
93 unsigned long last_updated; 89 unsigned long last_updated;
94 unsigned int cpu; 90 unsigned int cpu;
95 u32 cpu_core_id; 91 u32 cpu_core_id;
96 u32 status_reg; 92 u32 status_reg;
97 u32 intrpt_reg;
98 int attr_size; 93 int attr_size;
99 bool is_pkg_data; 94 bool is_pkg_data;
100 bool valid; 95 bool valid;
@@ -152,19 +147,6 @@ static ssize_t show_crit_alarm(struct device *dev,
152 return sprintf(buf, "%d\n", (eax >> 5) & 1); 147 return sprintf(buf, "%d\n", (eax >> 5) & 1);
153} 148}
154 149
155static ssize_t show_max_alarm(struct device *dev,
156 struct device_attribute *devattr, char *buf)
157{
158 u32 eax, edx;
159 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
160 struct platform_data *pdata = dev_get_drvdata(dev);
161 struct temp_data *tdata = pdata->core_data[attr->index];
162
163 rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
164
165 return sprintf(buf, "%d\n", !!(eax & THERM_STATUS_THRESHOLD1));
166}
167
168static ssize_t show_tjmax(struct device *dev, 150static ssize_t show_tjmax(struct device *dev,
169 struct device_attribute *devattr, char *buf) 151 struct device_attribute *devattr, char *buf)
170{ 152{
@@ -183,83 +165,6 @@ static ssize_t show_ttarget(struct device *dev,
183 return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); 165 return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);
184} 166}
185 167
186static ssize_t store_ttarget(struct device *dev,
187 struct device_attribute *devattr,
188 const char *buf, size_t count)
189{
190 struct platform_data *pdata = dev_get_drvdata(dev);
191 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
192 struct temp_data *tdata = pdata->core_data[attr->index];
193 u32 eax, edx;
194 unsigned long val;
195 int diff;
196
197 if (strict_strtoul(buf, 10, &val))
198 return -EINVAL;
199
200 /*
201 * THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms
202 * of milli degree celsius. Hence don't accept val > (127 * 1000)
203 */
204 if (val > tdata->tjmax || val > 127000)
205 return -EINVAL;
206
207 diff = (tdata->tjmax - val) / 1000;
208
209 mutex_lock(&tdata->update_lock);
210 rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
211 eax = (eax & ~THERM_MASK_THRESHOLD1) |
212 (diff << THERM_SHIFT_THRESHOLD1);
213 wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
214 tdata->ttarget = val;
215 mutex_unlock(&tdata->update_lock);
216
217 return count;
218}
219
220static ssize_t show_tmin(struct device *dev,
221 struct device_attribute *devattr, char *buf)
222{
223 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
224 struct platform_data *pdata = dev_get_drvdata(dev);
225
226 return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin);
227}
228
229static ssize_t store_tmin(struct device *dev,
230 struct device_attribute *devattr,
231 const char *buf, size_t count)
232{
233 struct platform_data *pdata = dev_get_drvdata(dev);
234 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
235 struct temp_data *tdata = pdata->core_data[attr->index];
236 u32 eax, edx;
237 unsigned long val;
238 int diff;
239
240 if (strict_strtoul(buf, 10, &val))
241 return -EINVAL;
242
243 /*
244 * THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms
245 * of milli degree celsius. Hence don't accept val > (127 * 1000)
246 */
247 if (val > tdata->tjmax || val > 127000)
248 return -EINVAL;
249
250 diff = (tdata->tjmax - val) / 1000;
251
252 mutex_lock(&tdata->update_lock);
253 rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
254 eax = (eax & ~THERM_MASK_THRESHOLD0) |
255 (diff << THERM_SHIFT_THRESHOLD0);
256 wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
257 tdata->tmin = val;
258 mutex_unlock(&tdata->update_lock);
259
260 return count;
261}
262
263static ssize_t show_temp(struct device *dev, 168static ssize_t show_temp(struct device *dev,
264 struct device_attribute *devattr, char *buf) 169 struct device_attribute *devattr, char *buf)
265{ 170{
@@ -445,16 +350,11 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
445 static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev, 350 static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev,
446 struct device_attribute *devattr, char *buf) = { 351 struct device_attribute *devattr, char *buf) = {
447 show_label, show_crit_alarm, show_temp, show_tjmax, 352 show_label, show_crit_alarm, show_temp, show_tjmax,
448 show_max_alarm, show_ttarget, show_tmin }; 353 show_ttarget };
449 static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev,
450 struct device_attribute *devattr, const char *buf,
451 size_t count) = { NULL, NULL, NULL, NULL, NULL,
452 store_ttarget, store_tmin };
453 static const char *names[TOTAL_ATTRS] = { 354 static const char *names[TOTAL_ATTRS] = {
454 "temp%d_label", "temp%d_crit_alarm", 355 "temp%d_label", "temp%d_crit_alarm",
455 "temp%d_input", "temp%d_crit", 356 "temp%d_input", "temp%d_crit",
456 "temp%d_max_alarm", "temp%d_max", 357 "temp%d_max" };
457 "temp%d_max_hyst" };
458 358
459 for (i = 0; i < tdata->attr_size; i++) { 359 for (i = 0; i < tdata->attr_size; i++) {
460 snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], 360 snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
@@ -462,10 +362,6 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
462 sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); 362 sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
463 tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; 363 tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
464 tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; 364 tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
465 if (rw_ptr[i]) {
466 tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
467 tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
468 }
469 tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; 365 tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
470 tdata->sd_attrs[i].index = attr_no; 366 tdata->sd_attrs[i].index = attr_no;
471 err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); 367 err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr);
@@ -538,8 +434,6 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
538 434
539 tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : 435 tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS :
540 MSR_IA32_THERM_STATUS; 436 MSR_IA32_THERM_STATUS;
541 tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT :
542 MSR_IA32_THERM_INTERRUPT;
543 tdata->is_pkg_data = pkg_flag; 437 tdata->is_pkg_data = pkg_flag;
544 tdata->cpu = cpu; 438 tdata->cpu = cpu;
545 tdata->cpu_core_id = TO_CORE_ID(cpu); 439 tdata->cpu_core_id = TO_CORE_ID(cpu);
@@ -591,19 +485,18 @@ static int create_core_data(struct platform_data *pdata,
591 tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); 485 tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
592 486
593 /* 487 /*
594 * Test if we can access the intrpt register. If so, increase the 488 * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET.
595 * 'size' enough to have ttarget/tmin/max_alarm interfaces. 489 * The target temperature is available on older CPUs but not in this
596 * Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT 490 * register. Atoms don't have the register at all.
597 */ 491 */
598 err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx); 492 if (c->x86_model > 0xe && c->x86_model != 0x1c) {
599 if (!err) { 493 err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET,
600 tdata->attr_size += MAX_THRESH_ATTRS; 494 &eax, &edx);
601 tdata->tmin = tdata->tjmax - 495 if (!err) {
602 ((eax & THERM_MASK_THRESHOLD0) >> 496 tdata->ttarget
603 THERM_SHIFT_THRESHOLD0) * 1000; 497 = tdata->tjmax - ((eax >> 8) & 0xff) * 1000;
604 tdata->ttarget = tdata->tjmax - 498 tdata->attr_size++;
605 ((eax & THERM_MASK_THRESHOLD1) >> 499 }
606 THERM_SHIFT_THRESHOLD1) * 1000;
607 } 500 }
608 501
609 pdata->core_data[attr_no] = tdata; 502 pdata->core_data[attr_no] = tdata;