* Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp
@ 2010-12-08 9:10 R, Durgadoss
2010-12-08 14:49 ` [lm-sensors] " Guenter Roeck
2010-12-08 15:22 ` Jean Delvare
0 siblings, 2 replies; 5+ messages in thread
From: R, Durgadoss @ 2010-12-08 9:10 UTC (permalink / raw)
To: Yu, Fenghua
Cc: lenb@kernel.org, linux-acpi@vger.kernel.org,
lm-sensors@lm-sensors.org, Zhang, Rui, R, Durgadoss
[-- Attachment #1: Type: text/plain, Size: 11888 bytes --]
Hi Fenghua,
This patch adds the core and package thermal threshold support to coretemp.c.
These thresholds can be read/written using the hwmon sysfs interfaces
temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
These thresholds are managed dynamically to generate interrupts,
to do power management.
This patch is generated against the stable Linux-2.6 tree.
Kindly review and merge.
-------------------------------------------------------------------------
From: Durgadoss R <durgadoss.r@intel.com>
Date: Tue, 7 Dec 2010 03:27:00 +0530
Subject: [PATCH 1/2] Adding_Threshold_support_to_coretemp
This patch adds the core and package threshold support to coretemp.c.
These thresholds can be read/written using the sysfs interfaces
temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
These can be used to generate interrupts, to do dynamic power management.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
arch/x86/include/asm/msr-index.h | 12 ++
drivers/hwmon/coretemp.c | 225 +++++++++++++++++++++++++++++++++++++-
2 files changed, 233 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 3ea3dc4..f0fea26 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -253,6 +253,18 @@
#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1)
#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24)
+/* Threshold Support */
+#define THERM_INT_THRESHOLD0_ENABLE (1 << 15)
+#define THERM_OFFSET_THRESHOLD0 8
+#define THERM_MASK_THRESHOLD0 (0x7f << THERM_OFFSET_THRESHOLD0)
+#define THERM_INT_THRESHOLD1_ENABLE (1 << 23)
+#define THERM_OFFSET_THRESHOLD1 16
+#define THERM_MASK_THRESHOLD1 (0x7f << THERM_OFFSET_THRESHOLD1)
+#define THERM_STATUS_THRESHOLD0 (1 << 6)
+#define THERM_LOG_THRESHOLD0 (1 << 7)
+#define THERM_STATUS_THRESHOLD1 (1 << 8)
+#define THERM_LOG_THRESHOLD1 (1 << 9)
+
/* MISC_ENABLE bits: architectural */
#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0)
#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1)
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 42de98d..7aea83e 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -41,6 +41,10 @@
typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL,
SHOW_NAME } SHOW;
+/* C indicates core thermal thresholds
+ * P indicates Package thermal thresholds
+ */
+enum thresholds { C_TTHRESH0, C_TTHRESH1, P_TTHRESH0, P_TTHRESH1 } THRESH;
/*
* Functions declaration
@@ -59,9 +63,18 @@ struct coretemp_data {
int temp;
int tjmax;
int ttarget;
+ int c_tthresh0;
+ int c_tthresh1;
+ int p_tthresh0;
+ int p_tthresh1;
+ int pkg_support; /* zero if pkg thresh support is not there */
u8 alarm;
};
+static int set_core_threshold(struct coretemp_data *data, int val,
+ enum thresholds thresh);
+static int set_pkg_threshold(struct coretemp_data *data, int val,
+ enum thresholds thresh);
/*
* Sysfs stuff
*/
@@ -104,6 +117,48 @@ static ssize_t show_temp(struct device *dev,
return err;
}
+static ssize_t show_threshold(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct coretemp_data *data = coretemp_update_device(dev);
+
+ if (!data->valid)
+ return -EINVAL;
+
+ switch (attr->index) {
+ case C_TTHRESH0:
+ return sprintf(buf, "%d\n", data->c_tthresh0);
+ case C_TTHRESH1:
+ return sprintf(buf, "%d\n", data->c_tthresh1);
+ case P_TTHRESH0:
+ return sprintf(buf, "%d\n", data->p_tthresh0);
+ case P_TTHRESH1:
+ return sprintf(buf, "%d\n", data->p_tthresh1);
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t set_threshold(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct coretemp_data *data = coretemp_update_device(dev);
+ unsigned long val;
+ int err;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ if (attr->index == C_TTHRESH0 || attr->index == C_TTHRESH1)
+ err = set_core_threshold(data, val, attr->index);
+ else
+ err = set_pkg_threshold(data, val, attr->index);
+
+ return (err) ? -EINVAL : count;
+}
+
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
SHOW_TEMP);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
@@ -114,12 +169,23 @@ static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+static SENSOR_DEVICE_ATTR(temp1_core_thresh0, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, C_TTHRESH0);
+static SENSOR_DEVICE_ATTR(temp1_core_thresh1, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, C_TTHRESH1);
+static SENSOR_DEVICE_ATTR(temp1_pkg_thresh0, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, P_TTHRESH0);
+static SENSOR_DEVICE_ATTR(temp1_pkg_thresh1, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, P_TTHRESH1);
+
static struct attribute *coretemp_attributes[] = {
&sensor_dev_attr_name.dev_attr.attr,
&sensor_dev_attr_temp1_label.dev_attr.attr,
&dev_attr_temp1_crit_alarm.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
+ &sensor_dev_attr_temp1_core_thresh0.dev_attr.attr,
+ &sensor_dev_attr_temp1_core_thresh1.dev_attr.attr,
NULL
};
@@ -298,6 +364,114 @@ static void __devinit get_ucode_rev_on_cpu(void *edx)
rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
}
+static int set_core_threshold(struct coretemp_data *data, int temp,
+ enum thresholds thresh)
+{
+ u32 eax, edx, l;
+ int diff;
+
+ if (temp > data->tjmax)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+
+ diff = (data->tjmax - temp)/1000;
+
+ /* Mask the thermal vector in the lapic */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
+
+ rdmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, &eax, &edx);
+
+ if (thresh == C_TTHRESH0) {
+ eax = (eax & ~THERM_MASK_THRESHOLD0) |
+ (diff << THERM_OFFSET_THRESHOLD0);
+ data->c_tthresh0 = temp;
+ } else {
+ eax = (eax & ~THERM_MASK_THRESHOLD1) |
+ (diff << THERM_OFFSET_THRESHOLD1);
+ data->c_tthresh1 = temp;
+ }
+
+ wrmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, eax, edx);
+
+ /* Unmask the thermal vector */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+ mutex_unlock(&data->update_lock);
+ return 0;
+}
+
+static int set_pkg_threshold(struct coretemp_data *data, int temp,
+ enum thresholds thresh)
+{
+ u32 eax, edx, l;
+ int diff;
+
+ if (temp > data->tjmax)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+
+ diff = (data->tjmax - temp)/1000;
+
+ /* Mask the thermal vector in the lapic */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
+
+ rdmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
+
+ if (thresh == P_TTHRESH0) {
+ eax = (eax & ~THERM_MASK_THRESHOLD0) |
+ (diff << THERM_OFFSET_THRESHOLD0);
+ data->p_tthresh0 = temp;
+ } else {
+ eax = (eax & ~THERM_MASK_THRESHOLD1) |
+ (diff << THERM_OFFSET_THRESHOLD1);
+ data->p_tthresh1 = temp;
+ }
+
+ wrmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, eax, edx);
+
+ /* Unmask the thermal vector */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+ mutex_unlock(&data->update_lock);
+ return 0;
+}
+
+static int __devinit enable_thresh_support(struct coretemp_data *data)
+{
+ u32 eax, edx, l;
+
+ /* Mask the thermal vector in the lapic */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
+
+ rdmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, &eax, &edx);
+
+ eax |= (THERM_INT_THRESHOLD0_ENABLE | THERM_INT_THRESHOLD1_ENABLE);
+
+ wrmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, eax, edx);
+
+ if (!data->pkg_support)
+ goto exit;
+
+ rdmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
+
+ eax |= (THERM_INT_THRESHOLD0_ENABLE | THERM_INT_THRESHOLD1_ENABLE);
+
+ wrmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, eax, edx);
+
+exit:
+ /* Unmask the thermal vector */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+ return 0;
+}
+
static int __devinit coretemp_probe(struct platform_device *pdev)
{
struct coretemp_data *data;
@@ -316,8 +490,11 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
data->core_id = c->cpu_core_id;
#endif
data->name = "coretemp";
- mutex_init(&data->update_lock);
+ if (cpu_has(c, X86_FEATURE_PTS))
+ data->pkg_support = 1;
+
+ mutex_init(&data->update_lock);
/* test if we can access the THERM_STATUS MSR */
err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
if (err) {
@@ -353,6 +530,30 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
data->tjmax = get_tjmax(c, data->id, &pdev->dev);
platform_set_drvdata(pdev, data);
+ /* Enable threshold support */
+ enable_thresh_support(data);
+
+ /* Set Initial Core thresholds */
+ set_core_threshold(data, 0, C_TTHRESH0);
+ set_core_threshold(data, 90000, C_TTHRESH1);
+
+ /* Set Initial Package thresholds, if HW support is available */
+ if (data->pkg_support) {
+ set_pkg_threshold(data, 0, P_TTHRESH0);
+ set_pkg_threshold(data, 80000, P_TTHRESH1);
+ }
+
+ if (data->pkg_support) {
+ err = device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh0.dev_attr);
+ if (err)
+ goto exit_free;
+ err = device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh1.dev_attr);
+ if (err)
+ goto exit_pkg_thresh0;
+ }
+
/*
* read the still undocumented IA32_TEMPERATURE_TARGET. It exists
* on older CPUs but not in this register,
@@ -371,12 +572,12 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
err = device_create_file(&pdev->dev,
&sensor_dev_attr_temp1_max.dev_attr);
if (err)
- goto exit_free;
+ goto exit_pkg_thresh1;
}
}
if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
- goto exit_dev;
+ goto exit_dev_max;
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -390,8 +591,14 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
exit_class:
sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
-exit_dev:
+exit_dev_max:
device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+exit_pkg_thresh1:
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh1.dev_attr);
+exit_pkg_thresh0:
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh0.dev_attr);
exit_free:
kfree(data);
exit:
@@ -405,6 +612,16 @@ static int __devexit coretemp_remove(struct platform_device *pdev)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_core_thresh0.dev_attr);
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_core_thresh1.dev_attr);
+ if (data->pkg_support) {
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh0.dev_attr);
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh1.dev_attr);
+ }
platform_set_drvdata(pdev, NULL);
kfree(data);
return 0;
--
1.6.5.2
[-- Attachment #2: 0001-Adding_Threshold_support_to_coretemp.patch --]
[-- Type: application/octet-stream, Size: 11053 bytes --]
From: Durgadoss R <durgadoss.r@intel.com>
Date: Tue, 7 Dec 2010 03:27:00 +0530
Subject: [PATCH 1/2] Adding_Threshold_support_to_coretemp
This patch adds the core and package threshold support to coretemp.c.
These thresholds can be read/written using the sysfs interfaces
temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
These can be used to generate interrupts, to do dynamic power management.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
arch/x86/include/asm/msr-index.h | 12 ++
drivers/hwmon/coretemp.c | 225 +++++++++++++++++++++++++++++++++++++-
2 files changed, 233 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 3ea3dc4..f0fea26 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -253,6 +253,18 @@
#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1)
#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24)
+/* Threshold Support */
+#define THERM_INT_THRESHOLD0_ENABLE (1 << 15)
+#define THERM_OFFSET_THRESHOLD0 8
+#define THERM_MASK_THRESHOLD0 (0x7f << THERM_OFFSET_THRESHOLD0)
+#define THERM_INT_THRESHOLD1_ENABLE (1 << 23)
+#define THERM_OFFSET_THRESHOLD1 16
+#define THERM_MASK_THRESHOLD1 (0x7f << THERM_OFFSET_THRESHOLD1)
+#define THERM_STATUS_THRESHOLD0 (1 << 6)
+#define THERM_LOG_THRESHOLD0 (1 << 7)
+#define THERM_STATUS_THRESHOLD1 (1 << 8)
+#define THERM_LOG_THRESHOLD1 (1 << 9)
+
/* MISC_ENABLE bits: architectural */
#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0)
#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1)
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 42de98d..7aea83e 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -41,6 +41,10 @@
typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL,
SHOW_NAME } SHOW;
+/* C indicates core thermal thresholds
+ * P indicates Package thermal thresholds
+ */
+enum thresholds { C_TTHRESH0, C_TTHRESH1, P_TTHRESH0, P_TTHRESH1 } THRESH;
/*
* Functions declaration
@@ -59,9 +63,18 @@ struct coretemp_data {
int temp;
int tjmax;
int ttarget;
+ int c_tthresh0;
+ int c_tthresh1;
+ int p_tthresh0;
+ int p_tthresh1;
+ int pkg_support; /* zero if pkg thresh support is not there */
u8 alarm;
};
+static int set_core_threshold(struct coretemp_data *data, int val,
+ enum thresholds thresh);
+static int set_pkg_threshold(struct coretemp_data *data, int val,
+ enum thresholds thresh);
/*
* Sysfs stuff
*/
@@ -104,6 +117,48 @@ static ssize_t show_temp(struct device *dev,
return err;
}
+static ssize_t show_threshold(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct coretemp_data *data = coretemp_update_device(dev);
+
+ if (!data->valid)
+ return -EINVAL;
+
+ switch (attr->index) {
+ case C_TTHRESH0:
+ return sprintf(buf, "%d\n", data->c_tthresh0);
+ case C_TTHRESH1:
+ return sprintf(buf, "%d\n", data->c_tthresh1);
+ case P_TTHRESH0:
+ return sprintf(buf, "%d\n", data->p_tthresh0);
+ case P_TTHRESH1:
+ return sprintf(buf, "%d\n", data->p_tthresh1);
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t set_threshold(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct coretemp_data *data = coretemp_update_device(dev);
+ unsigned long val;
+ int err;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ if (attr->index == C_TTHRESH0 || attr->index == C_TTHRESH1)
+ err = set_core_threshold(data, val, attr->index);
+ else
+ err = set_pkg_threshold(data, val, attr->index);
+
+ return (err) ? -EINVAL : count;
+}
+
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
SHOW_TEMP);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
@@ -114,12 +169,23 @@ static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+static SENSOR_DEVICE_ATTR(temp1_core_thresh0, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, C_TTHRESH0);
+static SENSOR_DEVICE_ATTR(temp1_core_thresh1, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, C_TTHRESH1);
+static SENSOR_DEVICE_ATTR(temp1_pkg_thresh0, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, P_TTHRESH0);
+static SENSOR_DEVICE_ATTR(temp1_pkg_thresh1, S_IWUSR | S_IRUGO,
+ show_threshold, set_threshold, P_TTHRESH1);
+
static struct attribute *coretemp_attributes[] = {
&sensor_dev_attr_name.dev_attr.attr,
&sensor_dev_attr_temp1_label.dev_attr.attr,
&dev_attr_temp1_crit_alarm.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
+ &sensor_dev_attr_temp1_core_thresh0.dev_attr.attr,
+ &sensor_dev_attr_temp1_core_thresh1.dev_attr.attr,
NULL
};
@@ -298,6 +364,114 @@ static void __devinit get_ucode_rev_on_cpu(void *edx)
rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
}
+static int set_core_threshold(struct coretemp_data *data, int temp,
+ enum thresholds thresh)
+{
+ u32 eax, edx, l;
+ int diff;
+
+ if (temp > data->tjmax)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+
+ diff = (data->tjmax - temp)/1000;
+
+ /* Mask the thermal vector in the lapic */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
+
+ rdmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, &eax, &edx);
+
+ if (thresh == C_TTHRESH0) {
+ eax = (eax & ~THERM_MASK_THRESHOLD0) |
+ (diff << THERM_OFFSET_THRESHOLD0);
+ data->c_tthresh0 = temp;
+ } else {
+ eax = (eax & ~THERM_MASK_THRESHOLD1) |
+ (diff << THERM_OFFSET_THRESHOLD1);
+ data->c_tthresh1 = temp;
+ }
+
+ wrmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, eax, edx);
+
+ /* Unmask the thermal vector */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+ mutex_unlock(&data->update_lock);
+ return 0;
+}
+
+static int set_pkg_threshold(struct coretemp_data *data, int temp,
+ enum thresholds thresh)
+{
+ u32 eax, edx, l;
+ int diff;
+
+ if (temp > data->tjmax)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+
+ diff = (data->tjmax - temp)/1000;
+
+ /* Mask the thermal vector in the lapic */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
+
+ rdmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
+
+ if (thresh == P_TTHRESH0) {
+ eax = (eax & ~THERM_MASK_THRESHOLD0) |
+ (diff << THERM_OFFSET_THRESHOLD0);
+ data->p_tthresh0 = temp;
+ } else {
+ eax = (eax & ~THERM_MASK_THRESHOLD1) |
+ (diff << THERM_OFFSET_THRESHOLD1);
+ data->p_tthresh1 = temp;
+ }
+
+ wrmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, eax, edx);
+
+ /* Unmask the thermal vector */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+ mutex_unlock(&data->update_lock);
+ return 0;
+}
+
+static int __devinit enable_thresh_support(struct coretemp_data *data)
+{
+ u32 eax, edx, l;
+
+ /* Mask the thermal vector in the lapic */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l | APIC_LVT_MASKED);
+
+ rdmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, &eax, &edx);
+
+ eax |= (THERM_INT_THRESHOLD0_ENABLE | THERM_INT_THRESHOLD1_ENABLE);
+
+ wrmsr_on_cpu(data->id, MSR_IA32_THERM_INTERRUPT, eax, edx);
+
+ if (!data->pkg_support)
+ goto exit;
+
+ rdmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
+
+ eax |= (THERM_INT_THRESHOLD0_ENABLE | THERM_INT_THRESHOLD1_ENABLE);
+
+ wrmsr_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_INTERRUPT, eax, edx);
+
+exit:
+ /* Unmask the thermal vector */
+ l = apic_read(APIC_LVTTHMR);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+ return 0;
+}
+
static int __devinit coretemp_probe(struct platform_device *pdev)
{
struct coretemp_data *data;
@@ -316,8 +490,11 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
data->core_id = c->cpu_core_id;
#endif
data->name = "coretemp";
- mutex_init(&data->update_lock);
+ if (cpu_has(c, X86_FEATURE_PTS))
+ data->pkg_support = 1;
+
+ mutex_init(&data->update_lock);
/* test if we can access the THERM_STATUS MSR */
err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
if (err) {
@@ -353,6 +530,30 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
data->tjmax = get_tjmax(c, data->id, &pdev->dev);
platform_set_drvdata(pdev, data);
+ /* Enable threshold support */
+ enable_thresh_support(data);
+
+ /* Set Initial Core thresholds */
+ set_core_threshold(data, 0, C_TTHRESH0);
+ set_core_threshold(data, 90000, C_TTHRESH1);
+
+ /* Set Initial Package thresholds, if HW support is available */
+ if (data->pkg_support) {
+ set_pkg_threshold(data, 0, P_TTHRESH0);
+ set_pkg_threshold(data, 80000, P_TTHRESH1);
+ }
+
+ if (data->pkg_support) {
+ err = device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh0.dev_attr);
+ if (err)
+ goto exit_free;
+ err = device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh1.dev_attr);
+ if (err)
+ goto exit_pkg_thresh0;
+ }
+
/*
* read the still undocumented IA32_TEMPERATURE_TARGET. It exists
* on older CPUs but not in this register,
@@ -371,12 +572,12 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
err = device_create_file(&pdev->dev,
&sensor_dev_attr_temp1_max.dev_attr);
if (err)
- goto exit_free;
+ goto exit_pkg_thresh1;
}
}
if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
- goto exit_dev;
+ goto exit_dev_max;
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
@@ -390,8 +591,14 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
exit_class:
sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
-exit_dev:
+exit_dev_max:
device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+exit_pkg_thresh1:
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh1.dev_attr);
+exit_pkg_thresh0:
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh0.dev_attr);
exit_free:
kfree(data);
exit:
@@ -405,6 +612,16 @@ static int __devexit coretemp_remove(struct platform_device *pdev)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_core_thresh0.dev_attr);
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_core_thresh1.dev_attr);
+ if (data->pkg_support) {
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh0.dev_attr);
+ device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_pkg_thresh1.dev_attr);
+ }
platform_set_drvdata(pdev, NULL);
kfree(data);
return 0;
--
1.6.5.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [lm-sensors] Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp
2010-12-08 9:10 Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp R, Durgadoss
@ 2010-12-08 14:49 ` Guenter Roeck
2010-12-08 15:22 ` Jean Delvare
1 sibling, 0 replies; 5+ messages in thread
From: Guenter Roeck @ 2010-12-08 14:49 UTC (permalink / raw)
To: R, Durgadoss
Cc: Yu, Fenghua, linux-acpi@vger.kernel.org, Zhang, Rui,
lm-sensors@lm-sensors.org, lenb@kernel.org
On Wed, Dec 08, 2010 at 04:10:29AM -0500, R, Durgadoss wrote:
> Hi Fenghua,
>
> This patch adds the core and package thermal threshold support to coretemp.c.
> These thresholds can be read/written using the hwmon sysfs interfaces
> temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
>
I don't think adding attributes to the hwmon sysfs ABI without prior discussion
is a good idea. Besides, there may be other means to accomplish the same,
eg by using the tempX_emergency attribute.
Guenter
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [lm-sensors] Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp
2010-12-08 9:10 Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp R, Durgadoss
2010-12-08 14:49 ` [lm-sensors] " Guenter Roeck
@ 2010-12-08 15:22 ` Jean Delvare
2010-12-08 16:36 ` R, Durgadoss
2010-12-08 17:11 ` Guenter Roeck
1 sibling, 2 replies; 5+ messages in thread
From: Jean Delvare @ 2010-12-08 15:22 UTC (permalink / raw)
To: R, Durgadoss; +Cc: Yu, Fenghua, linux-acpi, Zhang, Rui, lm-sensors, lenb
On Wed, 8 Dec 2010 14:40:29 +0530, R, Durgadoss wrote:
> Hi Fenghua,
>
> This patch adds the core and package thermal threshold support to coretemp.c.
> These thresholds can be read/written using the hwmon sysfs interfaces
> temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
The package temperature isn't currently supported by the coretemp
driver but by the pkgtemp driver. It makes no sense to add support for
package thermal threshold to coretemp as long as the pkgtemp functionality
hasn't been merged back into coretemp. This was the plan, BTW, I
objected to the very existence of a separate pkgtemp driver since day
1, and I thought we had agreed that pkgtemp would be removed and its
functionality would be merged into coretemp.
> Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Please note also that we will need your full name for kernel
submissions.
--
Jean Delvare
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [lm-sensors] Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp
2010-12-08 15:22 ` Jean Delvare
@ 2010-12-08 16:36 ` R, Durgadoss
2010-12-08 17:11 ` Guenter Roeck
1 sibling, 0 replies; 5+ messages in thread
From: R, Durgadoss @ 2010-12-08 16:36 UTC (permalink / raw)
To: Jean Delvare
Cc: Yu, Fenghua, linux-acpi@vger.kernel.org, Zhang, Rui,
lm-sensors@lm-sensors.org, lenb@kernel.org
> > This patch adds the core and package thermal threshold support to coretemp.c.
> > These thresholds can be read/written using the hwmon sysfs interfaces
> > temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
>
> The package temperature isn't currently supported by the coretemp
> driver but by the pkgtemp driver. It makes no sense to add support for
> package thermal threshold to coretemp as long as the pkgtemp functionality
> hasn't been merged back into coretemp. This was the plan, BTW, I
> objected to the very existence of a separate pkgtemp driver since day
> 1, and I thought we had agreed that pkgtemp would be removed and its
> functionality would be merged into coretemp.
Ok. I did not know the existence of a pkgtemp driver.
Will look into the pkgtemp driver.
>
> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
>
> Please note also that we will need your full name for kernel
> submissions.
That's my Full name. All my official records as well as
Other patch submissions have this name only.
Thanks,
Durgadoss
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [lm-sensors] Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp
2010-12-08 15:22 ` Jean Delvare
2010-12-08 16:36 ` R, Durgadoss
@ 2010-12-08 17:11 ` Guenter Roeck
1 sibling, 0 replies; 5+ messages in thread
From: Guenter Roeck @ 2010-12-08 17:11 UTC (permalink / raw)
To: Jean Delvare
Cc: R, Durgadoss, Yu, Fenghua, Zhang, Rui, lm-sensors@lm-sensors.org,
lenb@kernel.org, linux-acpi@vger.kernel.org
On Wed, Dec 08, 2010 at 10:22:14AM -0500, Jean Delvare wrote:
> On Wed, 8 Dec 2010 14:40:29 +0530, R, Durgadoss wrote:
> > Hi Fenghua,
> >
> > This patch adds the core and package thermal threshold support to coretemp.c.
> > These thresholds can be read/written using the hwmon sysfs interfaces
> > temp1_core_thresh[0/1] and temp1_pkg_thresh[0/1].
>
> The package temperature isn't currently supported by the coretemp
> driver but by the pkgtemp driver. It makes no sense to add support for
> package thermal threshold to coretemp as long as the pkgtemp functionality
> hasn't been merged back into coretemp. This was the plan, BTW, I
> objected to the very existence of a separate pkgtemp driver since day
> 1, and I thought we had agreed that pkgtemp would be removed and its
> functionality would be merged into coretemp.
>
Doesn't seem to be happening. Maybe we should reject further changes (other than
bug fixes) for those drivers until the cleanup has been done.
What is your take on the ABI changes ? For me, there are two questions: Do we need
new attributes ? If we do, what should be the attribute name(s) and semantics ?
Guenter
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-12-08 17:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-08 9:10 Patch[1/2] Adding Core and Package Thermal Threshold Support to Coretemp R, Durgadoss
2010-12-08 14:49 ` [lm-sensors] " Guenter Roeck
2010-12-08 15:22 ` Jean Delvare
2010-12-08 16:36 ` R, Durgadoss
2010-12-08 17:11 ` Guenter Roeck
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox