* [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Support to
@ 2011-06-11 6:03 Durgadoss R
2011-06-13 17:14 ` [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Guenter Roeck
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Durgadoss R @ 2011-06-11 6:03 UTC (permalink / raw)
To: lm-sensors
This patch adds the core and pkg support to coretemp.
These thresholds can be configured via the sysfs interfaces tempX_max
and tempX_max_hyst. An interrupt is generated when CPU temperature reaches
or crosses above tempX_max OR drops below tempX_max_hyst.
This patch is based on the documentation in IA Manual vol 3A, that can be
downloaded from here:
http://download.intel.com/design/processor/manuals/253668.pdf
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
v1
* Initial code to add core/pkg threshold support
v2
* Rearranged the attrs in rd/wr arrays in create_core_attrs function
* Added code to conditionally create the ttarget/tmin/max_alarm interfaces
* Changed the MAX_ATTRS definition
* Added attr_size variable to temp_data structure
Documentation/hwmon/coretemp | 7 ++
drivers/hwmon/coretemp.c | 170 +++++++++++++++++++++++++++++++-----------
2 files changed, 132 insertions(+), 45 deletions(-)
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp
index f85e913..fa8776a 100644
--- a/Documentation/hwmon/coretemp
+++ b/Documentation/hwmon/coretemp
@@ -35,6 +35,13 @@ 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').
tempX_input - Core temperature (in millidegrees Celsius).
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_alarm - Set when Out-of-spec bit is set, never clears.
Correct CPU operation is no longer guaranteed.
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index de3d246..101a36b 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -44,7 +44,9 @@
#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 */
-#define MAX_ATTRS 5 /* Maximum no of per-core 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 + MAX_THRESH_ATTRS)
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
#ifdef CONFIG_SMP
@@ -67,6 +69,9 @@
* 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.
+ * @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.
* @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.
@@ -74,15 +79,18 @@
struct temp_data {
int temp;
int ttarget;
+ int tmin;
int tjmax;
unsigned long last_updated;
unsigned int cpu;
u32 cpu_core_id;
u32 status_reg;
+ u32 intrpt_reg;
+ int attr_size;
bool is_pkg_data;
bool valid;
- struct sensor_device_attribute sd_attrs[MAX_ATTRS];
- char attr_name[MAX_ATTRS][CORETEMP_NAME_LENGTH];
+ struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
+ char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
struct mutex update_lock;
};
@@ -137,6 +145,19 @@ static ssize_t show_crit_alarm(struct device *dev,
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_LOG_THRESHOLD1));
+}
+
static ssize_t show_tjmax(struct device *dev,
struct device_attribute *devattr, char *buf)
{
@@ -155,6 +176,77 @@ static ssize_t show_ttarget(struct device *dev,
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. So don't accept val > 127 */
+ if (val > tdata->tjmax || val > 127)
+ 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. So don't accept val > 127 */
+ if (val > tdata->tjmax || val > 127)
+ 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,
struct device_attribute *devattr, char *buf)
{
@@ -361,23 +453,30 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
int attr_no)
{
int err, i;
- static ssize_t (*rd_ptr[MAX_ATTRS]) (struct device *dev,
+ static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev,
struct device_attribute *devattr, char *buf) = {
- show_label, show_crit_alarm, show_ttarget,
- show_temp, show_tjmax };
- static const char *names[MAX_ATTRS] = {
+ show_label, show_crit_alarm, show_temp, show_tjmax,
+ show_max_alarm, show_ttarget, show_tmin };
+ static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev,
+ 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_max", "temp%d_input",
- "temp%d_crit" };
+ "temp%d_imput", "temp%d_crit",
+ "temp%d_max_alarm", "temp%d_max",
+ "temp%d_max_hyst" };
- for (i = 0; i < MAX_ATTRS; i++) {
+ for (i = 0; i < tdata->attr_size; i++) {
snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
attr_no);
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.mode = S_IRUGO;
+ if (rw_ptr[i])
+ tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
- tdata->sd_attrs[i].dev_attr.store = NULL;
+ tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
tdata->sd_attrs[i].index = attr_no;
err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr);
if (err)
@@ -391,38 +490,6 @@ exit_free:
return err;
}
-static void update_ttarget(__u8 cpu_model, struct temp_data *tdata,
- struct device *dev)
-{
- int err;
- u32 eax, edx;
-
- /*
- * Initialize ttarget value. Eventually this will be
- * initialized with the value from MSR_IA32_THERM_INTERRUPT
- * register. If IA32_TEMPERATURE_TARGET is supported, this
- * value will be over written below.
- * To Do: Patch to initialize ttarget from MSR_IA32_THERM_INTERRUPT
- */
- tdata->ttarget = tdata->tjmax - 20000;
-
- /*
- * Read the still undocumented IA32_TEMPERATURE_TARGET. It exists
- * on older CPUs but not in this register,
- * Atoms don't have it either.
- */
- if (cpu_model > 0xe && cpu_model != 0x1c) {
- err = rdmsr_safe_on_cpu(tdata->cpu,
- MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
- if (err) {
- dev_warn(dev,
- "Unable to read IA32_TEMPERATURE_TARGET MSR\n");
- } else {
- tdata->ttarget = tdata->tjmax -
- ((eax >> 8) & 0xff) * 1000;
- }
- }
-}
static int __devinit chk_ucode_version(struct platform_device *pdev)
{
@@ -481,9 +548,12 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_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->cpu = cpu;
tdata->cpu_core_id = TO_CORE_ID(cpu);
+ tdata->attr_size = MAX_CORE_ATTRS;
mutex_init(&tdata->update_lock);
return tdata;
}
@@ -533,7 +603,17 @@ static int create_core_data(struct platform_data *pdata,
else
tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
- update_ttarget(c->x86_model, tdata, &pdev->dev);
+ /*
+ * Test if we can access the intrpt register. If so, increase the
+ * 'size' enough to have ttarget/tmin/max_alarm interfaces.
+ * Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT
+ */
+ err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx);
+ if (!err) {
+ tdata->attr_size += MAX_THRESH_ATTRS;
+ tdata->ttarget = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
+ }
+
pdata->core_data[attr_no] = tdata;
/* Create sysfs interfaces */
@@ -570,7 +650,7 @@ static void coretemp_remove_core(struct platform_data *pdata,
struct temp_data *tdata = pdata->core_data[indx];
/* Remove the sysfs attributes */
- for (i = 0; i < MAX_ATTRS; i++)
+ for (i = 0; i < tdata->attr_size; i++)
device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
kfree(pdata->core_data[indx]);
--
1.6.1
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold
2011-06-11 6:03 [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Support to Durgadoss R
@ 2011-06-13 17:14 ` Guenter Roeck
2011-07-05 9:38 ` Jean Delvare
2011-07-05 10:15 ` R, Durgadoss
2 siblings, 0 replies; 4+ messages in thread
From: Guenter Roeck @ 2011-06-13 17:14 UTC (permalink / raw)
To: lm-sensors
Hi Durga,
On Sat, Jun 11, 2011 at 07:28:43AM -0400, Durgadoss R wrote:
> This patch adds the core and pkg support to coretemp.
> These thresholds can be configured via the sysfs interfaces tempX_max
> and tempX_max_hyst. An interrupt is generated when CPU temperature reaches
> or crosses above tempX_max OR drops below tempX_max_hyst.
>
> This patch is based on the documentation in IA Manual vol 3A, that can be
> downloaded from here:
> http://download.intel.com/design/processor/manuals/253668.pdf
>
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
[ ... ]
> + 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_max", "temp%d_input",
> - "temp%d_crit" };
> + "temp%d_imput", "temp%d_crit",
s/imput/input/
Seems like we need another round of detailed testing ...
> + "temp%d_max_alarm", "temp%d_max",
> + "temp%d_max_hyst" };
>
> - for (i = 0; i < MAX_ATTRS; i++) {
> + for (i = 0; i < tdata->attr_size; i++) {
> snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
> attr_no);
> 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.mode = S_IRUGO;
> + if (rw_ptr[i])
> + tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
> tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
> - tdata->sd_attrs[i].dev_attr.store = NULL;
> + tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
Since you check for rw_ptr above anyway, you might as well move this assignment
into the if branch above. The NULL assignment is not necessary anyway, since the
entire structure is pre-initialized from kzalloc().
Thanks,
Guenter
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold
2011-06-11 6:03 [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Support to Durgadoss R
2011-06-13 17:14 ` [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Guenter Roeck
@ 2011-07-05 9:38 ` Jean Delvare
2011-07-05 10:15 ` R, Durgadoss
2 siblings, 0 replies; 4+ messages in thread
From: Jean Delvare @ 2011-07-05 9:38 UTC (permalink / raw)
To: lm-sensors
On Mon, 13 Jun 2011 10:14:04 -0700, Guenter Roeck wrote:
> Hi Durga,
>
> On Sat, Jun 11, 2011 at 07:28:43AM -0400, Durgadoss R wrote:
> > This patch adds the core and pkg support to coretemp.
> > These thresholds can be configured via the sysfs interfaces tempX_max
> > and tempX_max_hyst. An interrupt is generated when CPU temperature reaches
> > or crosses above tempX_max OR drops below tempX_max_hyst.
> >
> > This patch is based on the documentation in IA Manual vol 3A, that can be
> > downloaded from here:
> > http://download.intel.com/design/processor/manuals/253668.pdf
> >
> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
>
> [ ... ]
>
> > + 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_max", "temp%d_input",
> > - "temp%d_crit" };
> > + "temp%d_imput", "temp%d_crit",
>
> s/imput/input/
>
> Seems like we need another round of detailed testing ...
>
> > + "temp%d_max_alarm", "temp%d_max",
> > + "temp%d_max_hyst" };
> >
> > - for (i = 0; i < MAX_ATTRS; i++) {
> > + for (i = 0; i < tdata->attr_size; i++) {
> > snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
> > attr_no);
> > 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.mode = S_IRUGO;
> > + if (rw_ptr[i])
> > + tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
> > tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
> > - tdata->sd_attrs[i].dev_attr.store = NULL;
> > + tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
>
> Since you check for rw_ptr above anyway, you might as well move this assignment
> into the if branch above. The NULL assignment is not necessary anyway, since the
> entire structure is pre-initialized from kzalloc().
Durgadoss, any progress on this? I also have coretemp patches pending,
I was originally waiting for yours to go in first, to avoid conflicts,
but I don't want to wait too long either...
--
Jean Delvare
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold
2011-06-11 6:03 [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Support to Durgadoss R
2011-06-13 17:14 ` [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Guenter Roeck
2011-07-05 9:38 ` Jean Delvare
@ 2011-07-05 10:15 ` R, Durgadoss
2 siblings, 0 replies; 4+ messages in thread
From: R, Durgadoss @ 2011-07-05 10:15 UTC (permalink / raw)
To: lm-sensors
Hi Jean,
>
> Durgadoss, any progress on this? I also have coretemp patches pending,
> I was originally waiting for yours to go in first, to avoid conflicts,
> but I don't want to wait too long either...
>
Sorry.. I will submit a v3 of this patch, in an hour..
Thanks,
Durga
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-07-05 10:15 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-11 6:03 [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Support to Durgadoss R
2011-06-13 17:14 ` [lm-sensors] [PATCHv2 1/1] Hwmon: Add core_pkg Threshold Guenter Roeck
2011-07-05 9:38 ` Jean Delvare
2011-07-05 10:15 ` R, Durgadoss
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.