Merge branch 'hwmon-for-linus' of git://github.com/groeck/linux

* 'hwmon-for-linus' of git://github.com/groeck/linux:
  hwmon: (coretemp) remove struct platform_data * parameter from create_core_data()
  hwmon: (coretemp) constify static data
  hwmon: (coretemp) don't use kernel assigned CPU number as platform device ID
  hwmon: (ds620) Fix handling of negative temperatures
  hwmon: (w83791d) rename prototype parameter from 'register' to 'reg'
  hwmon: (coretemp) Don't use threshold registers for tempX_max
  hwmon: (coretemp) Let the user force TjMax
  hwmon: (coretemp) Drop duplicate function get_pkg_tjmax
This commit is contained in:
Linus Torvalds 2011-09-26 13:35:43 -07:00
commit ef82bdc57a
4 changed files with 47 additions and 166 deletions

View file

@ -35,13 +35,6 @@ the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
All Sysfs entries are named with their core_id (represented here by 'X'). All Sysfs entries are named with their core_id (represented here by 'X').
tempX_input - Core temperature (in millidegrees Celsius). tempX_input - Core temperature (in millidegrees Celsius).
tempX_max - All cooling devices should be turned on (on Core2). tempX_max - All cooling devices should be turned on (on Core2).
Initialized with IA32_THERM_INTERRUPT. When the CPU
temperature reaches this temperature, an interrupt is
generated and tempX_max_alarm is set.
tempX_max_hyst - If the CPU temperature falls below than temperature,
an interrupt is generated and tempX_max_alarm is reset.
tempX_max_alarm - Set if the temperature reaches or exceeds tempX_max.
Reset if the temperature drops to or below tempX_max_hyst.
tempX_crit - Maximum junction temperature (in millidegrees Celsius). tempX_crit - Maximum junction temperature (in millidegrees Celsius).
tempX_crit_alarm - Set when Out-of-spec bit is set, never clears. tempX_crit_alarm - Set when Out-of-spec bit is set, never clears.
Correct CPU operation is no longer guaranteed. Correct CPU operation is no longer guaranteed.
@ -49,9 +42,10 @@ tempX_label - Contains string "Core X", where X is processor
number. For Package temp, this will be "Physical id Y", number. For Package temp, this will be "Physical id Y",
where Y is the package number. where Y is the package number.
The TjMax temperature is set to 85 degrees C if undocumented model specific On CPU models which support it, TjMax is read from a model-specific register.
register (UMSR) 0xee has bit 30 set. If not the TjMax is 100 degrees C as On other models, it is set to an arbitrary value based on weak heuristics.
(sometimes) documented in processor datasheet. If these heuristics don't work for you, you can pass the correct TjMax value
as a module parameter (tjmax).
Appendix A. Known TjMax lists (TBD): Appendix A. Known TjMax lists (TBD):
Some information comes from ark.intel.com Some information comes from ark.intel.com

View file

@ -36,17 +36,25 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/moduleparam.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/processor.h> #include <asm/processor.h>
#define DRVNAME "coretemp" #define DRVNAME "coretemp"
/*
* 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");
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
#define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ #define NUM_REAL_CORES 16 /* Number of Real cores per cpu */
#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
#define MAX_THRESH_ATTRS 3 /* Maximum no of Threshold attrs */ #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
#define TOTAL_ATTRS (MAX_CORE_ATTRS + MAX_THRESH_ATTRS)
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
@ -69,8 +77,6 @@
* This value is passed as "id" field to rdmsr/wrmsr functions. * This value is passed as "id" field to rdmsr/wrmsr functions.
* @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS,
* from where the temperature values should be read. * from where the temperature values should be read.
* @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT,
* from where the thresholds are read.
* @attr_size: Total number of pre-core attrs displayed in the sysfs. * @attr_size: Total number of pre-core attrs displayed in the sysfs.
* @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
* Otherwise, temp_data holds coretemp data. * Otherwise, temp_data holds coretemp data.
@ -79,13 +85,11 @@
struct temp_data { struct temp_data {
int temp; int temp;
int ttarget; int ttarget;
int tmin;
int tjmax; int tjmax;
unsigned long last_updated; unsigned long last_updated;
unsigned int cpu; unsigned int cpu;
u32 cpu_core_id; u32 cpu_core_id;
u32 status_reg; u32 status_reg;
u32 intrpt_reg;
int attr_size; int attr_size;
bool is_pkg_data; bool is_pkg_data;
bool valid; bool valid;
@ -143,19 +147,6 @@ static ssize_t show_crit_alarm(struct device *dev,
return sprintf(buf, "%d\n", (eax >> 5) & 1); return sprintf(buf, "%d\n", (eax >> 5) & 1);
} }
static ssize_t show_max_alarm(struct device *dev,
struct device_attribute *devattr, char *buf)
{
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\n", !!(eax & THERM_STATUS_THRESHOLD1));
}
static ssize_t show_tjmax(struct device *dev, static ssize_t show_tjmax(struct device *dev,
struct device_attribute *devattr, char *buf) struct device_attribute *devattr, char *buf)
{ {
@ -174,83 +165,6 @@ static ssize_t show_ttarget(struct device *dev,
return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);
} }
static ssize_t store_ttarget(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
struct platform_data *pdata = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct temp_data *tdata = pdata->core_data[attr->index];
u32 eax, edx;
unsigned long val;
int diff;
if (strict_strtoul(buf, 10, &val))
return -EINVAL;
/*
* THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms
* of milli degree celsius. Hence don't accept val > (127 * 1000)
*/
if (val > tdata->tjmax || val > 127000)
return -EINVAL;
diff = (tdata->tjmax - val) / 1000;
mutex_lock(&tdata->update_lock);
rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
eax = (eax & ~THERM_MASK_THRESHOLD1) |
(diff << THERM_SHIFT_THRESHOLD1);
wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
tdata->ttarget = val;
mutex_unlock(&tdata->update_lock);
return count;
}
static ssize_t show_tmin(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);
return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin);
}
static ssize_t store_tmin(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
struct platform_data *pdata = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct temp_data *tdata = pdata->core_data[attr->index];
u32 eax, edx;
unsigned long val;
int diff;
if (strict_strtoul(buf, 10, &val))
return -EINVAL;
/*
* THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms
* of milli degree celsius. Hence don't accept val > (127 * 1000)
*/
if (val > tdata->tjmax || val > 127000)
return -EINVAL;
diff = (tdata->tjmax - val) / 1000;
mutex_lock(&tdata->update_lock);
rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
eax = (eax & ~THERM_MASK_THRESHOLD0) |
(diff << THERM_SHIFT_THRESHOLD0);
wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
tdata->tmin = val;
mutex_unlock(&tdata->update_lock);
return count;
}
static ssize_t show_temp(struct device *dev, static ssize_t show_temp(struct device *dev,
struct device_attribute *devattr, char *buf) struct device_attribute *devattr, char *buf)
{ {
@ -374,7 +288,6 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
{ {
/* The 100C is default for both mobile and non mobile CPUs */
int err; int err;
u32 eax, edx; u32 eax, edx;
u32 val; u32 val;
@ -385,7 +298,8 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
*/ */
err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err) { if (err) {
dev_warn(dev, "Unable to read TjMax from CPU.\n"); if (c->x86_model > 0xe && c->x86_model != 0x1c)
dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
} else { } else {
val = (eax >> 16) & 0xff; val = (eax >> 16) & 0xff;
/* /*
@ -393,11 +307,17 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
* will be used * will be used
*/ */
if (val) { if (val) {
dev_info(dev, "TjMax is %d C.\n", val); dev_dbg(dev, "TjMax is %d degrees C\n", val);
return val * 1000; return val * 1000;
} }
} }
if (force_tjmax) {
dev_notice(dev, "TjMax forced to %d degrees C by user\n",
force_tjmax);
return force_tjmax * 1000;
}
/* /*
* An assumption is made for early CPUs and unreadable MSR. * An assumption is made for early CPUs and unreadable MSR.
* NOTE: the calculated value may not be correct. * NOTE: the calculated value may not be correct.
@ -414,21 +334,6 @@ static void __devinit get_ucode_rev_on_cpu(void *edx)
rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx); rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
} }
static int get_pkg_tjmax(unsigned int cpu, struct device *dev)
{
int err;
u32 eax, edx, val;
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (!err) {
val = (eax >> 16) & 0xff;
if (val)
return val * 1000;
}
dev_warn(dev, "Unable to read Pkg-TjMax from CPU:%u\n", cpu);
return 100000; /* Default TjMax: 100 degree celsius */
}
static int create_name_attr(struct platform_data *pdata, struct device *dev) static int create_name_attr(struct platform_data *pdata, struct device *dev)
{ {
sysfs_attr_init(&pdata->name_attr.attr); sysfs_attr_init(&pdata->name_attr.attr);
@ -442,19 +347,14 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
int attr_no) int attr_no)
{ {
int err, i; int err, i;
static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev, static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
struct device_attribute *devattr, char *buf) = { struct device_attribute *devattr, char *buf) = {
show_label, show_crit_alarm, show_temp, show_tjmax, show_label, show_crit_alarm, show_temp, show_tjmax,
show_max_alarm, show_ttarget, show_tmin }; show_ttarget };
static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev, static const char *const names[TOTAL_ATTRS] = {
struct device_attribute *devattr, const char *buf,
size_t count) = { NULL, NULL, NULL, NULL, NULL,
store_ttarget, store_tmin };
static const char *names[TOTAL_ATTRS] = {
"temp%d_label", "temp%d_crit_alarm", "temp%d_label", "temp%d_crit_alarm",
"temp%d_input", "temp%d_crit", "temp%d_input", "temp%d_crit",
"temp%d_max_alarm", "temp%d_max", "temp%d_max" };
"temp%d_max_hyst" };
for (i = 0; i < tdata->attr_size; i++) { for (i = 0; i < tdata->attr_size; i++) {
snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], 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,
sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; 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.attr.mode = S_IRUGO;
if (rw_ptr[i]) {
tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
}
tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
tdata->sd_attrs[i].index = attr_no; tdata->sd_attrs[i].index = attr_no;
err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); 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)
tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS :
MSR_IA32_THERM_STATUS; MSR_IA32_THERM_STATUS;
tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT :
MSR_IA32_THERM_INTERRUPT;
tdata->is_pkg_data = pkg_flag; tdata->is_pkg_data = pkg_flag;
tdata->cpu = cpu; tdata->cpu = cpu;
tdata->cpu_core_id = TO_CORE_ID(cpu); tdata->cpu_core_id = TO_CORE_ID(cpu);
@ -548,11 +442,11 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
return tdata; return tdata;
} }
static int create_core_data(struct platform_data *pdata, static int create_core_data(struct platform_device *pdev,
struct platform_device *pdev,
unsigned int cpu, int pkg_flag) unsigned int cpu, int pkg_flag)
{ {
struct temp_data *tdata; struct temp_data *tdata;
struct platform_data *pdata = platform_get_drvdata(pdev);
struct cpuinfo_x86 *c = &cpu_data(cpu); struct cpuinfo_x86 *c = &cpu_data(cpu);
u32 eax, edx; u32 eax, edx;
int err, attr_no; int err, attr_no;
@ -588,25 +482,21 @@ static int create_core_data(struct platform_data *pdata,
goto exit_free; goto exit_free;
/* We can access status register. Get Critical Temperature */ /* We can access status register. Get Critical Temperature */
if (pkg_flag) tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
tdata->tjmax = get_pkg_tjmax(pdev->id, &pdev->dev);
else
tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
/* /*
* Test if we can access the intrpt register. If so, increase the * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET.
* 'size' enough to have ttarget/tmin/max_alarm interfaces. * The target temperature is available on older CPUs but not in this
* Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT * register. Atoms don't have the register at all.
*/ */
err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx); if (c->x86_model > 0xe && c->x86_model != 0x1c) {
if (!err) { err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET,
tdata->attr_size += MAX_THRESH_ATTRS; &eax, &edx);
tdata->tmin = tdata->tjmax - if (!err) {
((eax & THERM_MASK_THRESHOLD0) >> tdata->ttarget
THERM_SHIFT_THRESHOLD0) * 1000; = tdata->tjmax - ((eax >> 8) & 0xff) * 1000;
tdata->ttarget = tdata->tjmax - tdata->attr_size++;
((eax & THERM_MASK_THRESHOLD1) >> }
THERM_SHIFT_THRESHOLD1) * 1000;
} }
pdata->core_data[attr_no] = tdata; pdata->core_data[attr_no] = tdata;
@ -624,16 +514,13 @@ exit_free:
static void coretemp_add_core(unsigned int cpu, int pkg_flag) static void coretemp_add_core(unsigned int cpu, int pkg_flag)
{ {
struct platform_data *pdata;
struct platform_device *pdev = coretemp_get_pdev(cpu); struct platform_device *pdev = coretemp_get_pdev(cpu);
int err; int err;
if (!pdev) if (!pdev)
return; return;
pdata = platform_get_drvdata(pdev); err = create_core_data(pdev, cpu, pkg_flag);
err = create_core_data(pdata, pdev, cpu, pkg_flag);
if (err) if (err)
dev_err(&pdev->dev, "Adding Core %u failed\n", cpu); dev_err(&pdev->dev, "Adding Core %u failed\n", cpu);
} }
@ -671,7 +558,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
if (err) if (err)
goto exit_free; goto exit_free;
pdata->phys_proc_id = TO_PHYS_ID(pdev->id); pdata->phys_proc_id = pdev->id;
platform_set_drvdata(pdev, pdata); platform_set_drvdata(pdev, pdata);
pdata->hwmon_dev = hwmon_device_register(&pdev->dev); pdata->hwmon_dev = hwmon_device_register(&pdev->dev);
@ -723,7 +610,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
mutex_lock(&pdev_list_mutex); mutex_lock(&pdev_list_mutex);
pdev = platform_device_alloc(DRVNAME, cpu); pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu));
if (!pdev) { if (!pdev) {
err = -ENOMEM; err = -ENOMEM;
pr_err("Device allocation failed\n"); pr_err("Device allocation failed\n");

View file

@ -72,7 +72,7 @@ struct ds620_data {
char valid; /* !=0 if following fields are valid */ char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
u16 temp[3]; /* Register values, word */ s16 temp[3]; /* Register values, word */
}; };
/* /*

View file

@ -329,8 +329,8 @@ static int w83791d_detect(struct i2c_client *client,
struct i2c_board_info *info); struct i2c_board_info *info);
static int w83791d_remove(struct i2c_client *client); static int w83791d_remove(struct i2c_client *client);
static int w83791d_read(struct i2c_client *client, u8 register); static int w83791d_read(struct i2c_client *client, u8 reg);
static int w83791d_write(struct i2c_client *client, u8 register, u8 value); static int w83791d_write(struct i2c_client *client, u8 reg, u8 value);
static struct w83791d_data *w83791d_update_device(struct device *dev); static struct w83791d_data *w83791d_update_device(struct device *dev);
#ifdef DEBUG #ifdef DEBUG