[PATCH RFC] Merging_Pkgtemp_with_Coretemp

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch merges the pkgtemp driver with the coretemp driver, by
creating the required pkg temp interfaces under the same
hwmonX/device directory as that of the coretemp.
None of the coretemp interfaces are changed.

Signed-off-by: Durgadoss R <durgadoss.r@xxxxxxxxx>
---
 drivers/hwmon/coretemp.c |  378 ++++++++++++++++++++++++++++++++++-----------
 1 files changed, 285 insertions(+), 93 deletions(-)

diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 42de98d..b3dae75 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -39,87 +39,134 @@
 
 #define DRVNAME	"coretemp"
 
-typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL,
-		SHOW_NAME } SHOW;
+static DEFINE_MUTEX(update_lock);
 
-/*
- * Functions declaration
- */
+enum { COREID, PHYS_PROCID, DRV_NAME };
+enum { CORE_TEMP, CORE_TJMAX, CORE_TTARGET, PKG_TEMP, PKG_TJMAX, PKG_TTARGET };
+enum { CORE_CRIT_ALARM, CORE_MAX_ALARM, PKG_CRIT_ALARM, PKG_MAX_ALARM };
 
-static struct coretemp_data *coretemp_update_device(struct device *dev);
-
-struct coretemp_data {
-	struct device *hwmon_dev;
-	struct mutex update_lock;
-	const char *name;
-	u32 id;
-	u16 core_id;
-	char valid;		/* zero until following fields are valid */
-	unsigned long last_updated;	/* in jiffies */
+struct temp_data {	/* Temperature Data common to both pkg and core */
 	int temp;
 	int tjmax;
 	int ttarget;
-	u8 alarm;
+	u8 crit_alarm;
+	u8 max_alarm;
+	unsigned long last_updated;	/* in jiffies */
 };
 
+struct cpu_id_info {
+	u32 id;
+	u16 core_id;
+	u16 phys_proc_id;
+};
+
+struct platform_data {
+	struct device *hwmon_dev;
+	const char *name;
+	int pkg_support;
+	struct cpu_id_info *cpu_data;
+	struct temp_data *core_data;
+	struct temp_data *pkg_data;
+};
+
+/* Functions Declaration */
+static int update_curr_temp(struct platform_data *pdata, int index);
+static void update_alarm(struct platform_data *pdata, int index);
+
 /*
  * Sysfs stuff
  */
 
 static ssize_t show_name(struct device *dev, struct device_attribute
-			  *devattr, char *buf)
+							  *devattr, char *buf)
 {
-	int ret;
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct coretemp_data *data = dev_get_drvdata(dev);
-
-	if (attr->index == SHOW_NAME)
-		ret = sprintf(buf, "%s\n", data->name);
-	else	/* show label */
-		ret = sprintf(buf, "Core %d\n", data->core_id);
-	return ret;
+	struct platform_data *data = dev_get_drvdata(dev);
+
+	switch (attr->index) {
+	case DRV_NAME:
+		return sprintf(buf, "%s\n", data->name);
+	case COREID:
+		return sprintf(buf, "Core %d\n", data->cpu_data->core_id);
+	case PHYS_PROCID:
+		return sprintf(buf, "Physical id %d\n",
+						data->cpu_data->phys_proc_id);
+	default:
+		return -EINVAL;
+	}
 }
 
 static ssize_t show_alarm(struct device *dev, struct device_attribute
-			  *devattr, char *buf)
+							  *devattr, char *buf)
 {
-	struct coretemp_data *data = coretemp_update_device(dev);
-	/* read the Out-of-spec log, never clear */
-	return sprintf(buf, "%d\n", data->alarm);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct platform_data *data = dev_get_drvdata(dev);
+
+	update_alarm(data, attr->index);
+
+	switch (attr->index) {
+	case CORE_CRIT_ALARM:
+		return sprintf(buf, "%d\n", data->core_data->crit_alarm);
+	case CORE_MAX_ALARM:
+		return sprintf(buf, "%d\n", data->core_data->max_alarm);
+	case PKG_CRIT_ALARM:
+		return sprintf(buf, "%d\n", data->pkg_data->crit_alarm);
+	case PKG_MAX_ALARM:
+		return sprintf(buf, "%d\n", data->pkg_data->max_alarm);
+	default:
+		return -EINVAL;
+	}
 }
 
 static ssize_t show_temp(struct device *dev,
-			 struct device_attribute *devattr, char *buf)
+				struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct coretemp_data *data = coretemp_update_device(dev);
+	struct platform_data *data = dev_get_drvdata(dev);
 	int err;
 
-	if (attr->index == SHOW_TEMP)
-		err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
-	else if (attr->index == SHOW_TJMAX)
-		err = sprintf(buf, "%d\n", data->tjmax);
-	else
-		err = sprintf(buf, "%d\n", data->ttarget);
-	return err;
+	switch (attr->index) {
+	case CORE_TEMP:
+		err = update_curr_temp(data, CORE_TEMP);
+		return err ? err : sprintf(buf, "%d\n", data->core_data->temp);
+	case PKG_TEMP:
+		err = update_curr_temp(data, PKG_TEMP);
+		return err ? err : sprintf(buf, "%d\n", data->pkg_data->temp);
+	case CORE_TJMAX:
+		return sprintf(buf, "%d\n", data->core_data->tjmax);
+	case CORE_TTARGET:
+		return sprintf(buf, "%d\n", data->core_data->ttarget);
+	default:
+		return -EINVAL;
+	}
 }
 
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
-			  SHOW_TEMP);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
-			  SHOW_TJMAX);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL,
-			  SHOW_TTARGET);
-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);
+/* Coretemp attributes */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, CORE_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, CORE_TJMAX);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, CORE_TTARGET);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL,
+							CORE_CRIT_ALARM);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
+							CORE_MAX_ALARM);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, COREID);
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, DRV_NAME);
+/* Packagetemp attributes */
+static SENSOR_DEVICE_ATTR(temp1_pkg_input, S_IRUGO, show_temp, NULL, PKG_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_pkg_crit_alarm, S_IRUGO, show_alarm, NULL,
+							PKG_CRIT_ALARM);
+static SENSOR_DEVICE_ATTR(temp1_pkg_max_alarm, S_IRUGO, show_alarm, NULL,
+							PKG_MAX_ALARM);
+static SENSOR_DEVICE_ATTR(temp1_pkg_id, S_IRUGO, show_name, NULL, PHYS_PROCID);
+
 
 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_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_label.dev_attr.attr,
+	&sensor_dev_attr_name.dev_attr.attr,
 	NULL
 };
 
@@ -127,31 +174,62 @@ static const struct attribute_group coretemp_group = {
 	.attrs = coretemp_attributes,
 };
 
-static struct coretemp_data *coretemp_update_device(struct device *dev)
+static void update_alarm(struct platform_data *data, int index)
+{
+	u32 eax, edx;
+	struct temp_data *tdata;
+
+	if (index == CORE_CRIT_ALARM || index == CORE_MAX_ALARM) {
+		rdmsr_on_cpu(data->cpu_data->id, MSR_IA32_THERM_STATUS,
+								&eax, &edx);
+		tdata = data->core_data;
+	} else {
+		rdmsr_on_cpu(data->cpu_data->id, MSR_IA32_PACKAGE_THERM_STATUS,
+								&eax, &edx);
+		tdata = data->pkg_data;
+	}
+	/* Update the critical temperature alarm */
+	tdata->crit_alarm = (eax >> 5) & 1;
+	return;
+}
+
+static int update_curr_temp(struct platform_data *data, int index)
 {
-	struct coretemp_data *data = dev_get_drvdata(dev);
+	struct temp_data *tdata;
+	struct cpu_id_info *cdata;
+	u32 eax, edx;
+	int err = 0;
+
+	mutex_lock(&update_lock);
 
-	mutex_lock(&data->update_lock);
+	cdata = data->cpu_data;
 
-	if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
-		u32 eax, edx;
+	if (index == CORE_TEMP) {
+		tdata = data->core_data;
+		rdmsr_on_cpu(cdata->id, MSR_IA32_THERM_STATUS, &eax, &edx);
+	} else {
+		tdata = data->pkg_data;
+		rdmsr_on_cpu(cdata->id, MSR_IA32_PACKAGE_THERM_STATUS,
+								&eax, &edx);
+	}
 
-		data->valid = 0;
-		rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
-		data->alarm = (eax >> 5) & 1;
+	if (time_after(jiffies, tdata->last_updated + HZ)) {
 		/* update only if data has been valid */
 		if (eax & 0x80000000) {
-			data->temp = data->tjmax - (((eax >> 16)
+			tdata->temp = tdata->tjmax - (((eax >> 16)
 							& 0x7f) * 1000);
-			data->valid = 1;
 		} else {
-			dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
+			dev_dbg(data->hwmon_dev,
+				"Temperature data invalid (0x%x)\n", eax);
+			err = -EINVAL;
+			goto exit;
 		}
-		data->last_updated = jiffies;
+		tdata->last_updated = jiffies;
 	}
 
-	mutex_unlock(&data->update_lock);
-	return data;
+exit:
+	mutex_unlock(&update_lock);
+	return err;
 }
 
 static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
@@ -298,32 +376,135 @@ static void __devinit get_ucode_rev_on_cpu(void *edx)
 	rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
 }
 
+static int init_core_data(struct platform_data *pdata)
+{
+	struct cpu_id_info *cinfo;
+	struct temp_data *core_data;
+
+	cinfo = kzalloc(sizeof(struct cpu_id_info), GFP_KERNEL);
+	if (!cinfo)
+		return -ENOMEM;
+
+	core_data = kzalloc(sizeof(struct temp_data), GFP_KERNEL);
+	if (!core_data) {
+		kfree(cinfo);
+		return -ENOMEM;
+	}
+
+	pdata->cpu_data = cinfo;
+	pdata->core_data = core_data;
+
+	return 0;
+}
+
+static int enable_pkg_attrs(struct platform_device *pdev, int flag)
+{
+	int err = 0;
+	u32 eax, edx;
+
+	/* If flag is Zero, remove all interfaces.
+	 * If non-zero, create pkg temp interfaces
+	 */
+	if (!flag)
+		goto exit_pkg_id;
+
+
+	/* Test if we can access the PACKAGE_THERM_STATUS MSR.
+	 * If we cannot access, do not create any interfaces; just return
+	 */
+	err = rdmsr_safe_on_cpu(pdev->id, MSR_IA32_PACKAGE_THERM_STATUS,
+								&eax, &edx);
+	if (err) {
+		dev_err(&pdev->dev,
+			"Can't read PACKAGE_THERM_STATUS MSR:%d\n", err);
+		return err;
+	}
+
+	err = device_create_file(&pdev->dev,
+				&sensor_dev_attr_temp1_pkg_input.dev_attr);
+	if (err)
+		return err;
+
+	err = device_create_file(&pdev->dev,
+			&sensor_dev_attr_temp1_pkg_crit_alarm.dev_attr);
+	if (err)
+		goto exit_input;
+
+	err = device_create_file(&pdev->dev,
+				&sensor_dev_attr_temp1_pkg_max_alarm.dev_attr);
+	if (err)
+		goto exit_crit_alarm;
+
+	err = device_create_file(&pdev->dev,
+				&sensor_dev_attr_temp1_pkg_id.dev_attr);
+	if (err)
+		goto exit_max_alarm;
+
+	return err;
+
+exit_pkg_id:
+	device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_pkg_id.dev_attr);
+exit_max_alarm:
+	device_remove_file(&pdev->dev,
+			&sensor_dev_attr_temp1_pkg_max_alarm.dev_attr);
+exit_crit_alarm:
+	device_remove_file(&pdev->dev,
+			&sensor_dev_attr_temp1_pkg_crit_alarm.dev_attr);
+exit_input:
+	device_remove_file(&pdev->dev,
+				&sensor_dev_attr_temp1_pkg_input.dev_attr);
+	return err;
+}
+
 static int __devinit coretemp_probe(struct platform_device *pdev)
 {
-	struct coretemp_data *data;
+	struct platform_data *pdata;
 	struct cpuinfo_x86 *c = &cpu_data(pdev->id);
 	int err;
 	u32 eax, edx;
 
-	if (!(data = kzalloc(sizeof(struct coretemp_data), GFP_KERNEL))) {
-		err = -ENOMEM;
+	pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL);
+	if (!pdata) {
 		dev_err(&pdev->dev, "Out of memory\n");
-		goto exit;
+		return -ENOMEM;
+	}
+
+	if (init_core_data(pdata)) {
+		dev_err(&pdev->dev, "Out of memory\n");
+		kfree(pdata);
+		return -ENOMEM;
+	}
+
+	/* Initialize Package Temp data */
+	pdata->pkg_support = cpu_has(c, X86_FEATURE_PTS) ? 1 : 0;
+	if (pdata->pkg_support) {
+		pdata->pkg_data = kzalloc(sizeof(struct temp_data),
+								GFP_KERNEL);
+		if (!pdata->pkg_data) {
+			err = -ENOMEM;
+			goto exit_free;
+		}
+		err = enable_pkg_attrs(pdev, 1);
+		if (err) {
+			pdata->pkg_support = 0;
+			kfree(pdata->pkg_data);
+			goto exit_free;
+		}
 	}
 
-	data->id = pdev->id;
+	pdata->cpu_data->id = pdev->id;
 #ifdef CONFIG_SMP
-	data->core_id = c->cpu_core_id;
+	pdata->cpu_data->core_id = c->cpu_core_id;
+	pdata->cpu_data->phys_proc_id = c->phys_proc_id;
 #endif
-	data->name = "coretemp";
-	mutex_init(&data->update_lock);
+	pdata->name = "coretemp";
 
 	/* test if we can access the THERM_STATUS MSR */
-	err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
+	err = rdmsr_safe_on_cpu(pdev->id, MSR_IA32_THERM_STATUS, &eax, &edx);
 	if (err) {
 		dev_err(&pdev->dev,
 			"Unable to access THERM_STATUS MSR, giving up\n");
-		goto exit_free;
+		goto exit_pkg;
 	}
 
 	/* Check if we have problem with errata AE18 of Core processors:
@@ -333,25 +514,25 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
 
 	if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
 		/* check for microcode update */
-		err = smp_call_function_single(data->id, get_ucode_rev_on_cpu,
-					       &edx, 1);
+		err = smp_call_function_single(pdev->id, get_ucode_rev_on_cpu,
+								&edx, 1);
 		if (err) {
 			dev_err(&pdev->dev,
 				"Cannot determine microcode revision of "
-				"CPU#%u (%d)!\n", data->id, err);
+				"CPU#%u (%d)!\n", pdev->id, err);
 			err = -ENODEV;
-			goto exit_free;
+			goto exit_pkg;
 		} else if (edx < 0x39) {
 			err = -ENODEV;
 			dev_err(&pdev->dev,
 				"Errata AE18 not fixed, update BIOS or "
 				"microcode of the CPU!\n");
-			goto exit_free;
+			goto exit_pkg;
 		}
 	}
 
-	data->tjmax = get_tjmax(c, data->id, &pdev->dev);
-	platform_set_drvdata(pdev, data);
+	pdata->core_data->tjmax = get_tjmax(c, pdev->id, &pdev->dev);
+	platform_set_drvdata(pdev, pdata);
 
 	/*
 	 * read the still undocumented IA32_TEMPERATURE_TARGET. It exists
@@ -360,29 +541,28 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
 	 */
 
 	if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) {
-		err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET,
-		    &eax, &edx);
+		err = rdmsr_safe_on_cpu(pdev->id,
+				MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
 		if (err) {
 			dev_warn(&pdev->dev, "Unable to read"
 					" IA32_TEMPERATURE_TARGET MSR\n");
 		} else {
-			data->ttarget = data->tjmax -
+			pdata->core_data->ttarget = pdata->core_data->tjmax -
 					(((eax >> 8) & 0xff) * 1000);
 			err = device_create_file(&pdev->dev,
 					&sensor_dev_attr_temp1_max.dev_attr);
 			if (err)
-				goto exit_free;
+				goto exit_pkg;
 		}
 	}
 
 	if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
 		goto exit_dev;
 
-	data->hwmon_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		dev_err(&pdev->dev, "Class registration failed (%d)\n",
-			err);
+	pdata->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(pdata->hwmon_dev)) {
+		err = PTR_ERR(pdata->hwmon_dev);
+		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
 		goto exit_class;
 	}
 
@@ -392,19 +572,31 @@ exit_class:
 	sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
 exit_dev:
 	device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+exit_pkg:
+	if (pdata->pkg_support) {
+		enable_pkg_attrs(pdev, 0);
+		kfree(pdata->pkg_data);
+	}
 exit_free:
-	kfree(data);
-exit:
+	kfree(pdata->cpu_data);
+	kfree(pdata->core_data);
+	kfree(pdata);
 	return err;
 }
 
 static int __devexit coretemp_remove(struct platform_device *pdev)
 {
-	struct coretemp_data *data = platform_get_drvdata(pdev);
+	struct platform_data *data = platform_get_drvdata(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);
+	if (data->pkg_support) {
+		enable_pkg_attrs(pdev, 0);
+		kfree(data->pkg_data);
+	}
+	kfree(data->cpu_data);
+	kfree(data->core_data);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 	return 0;
-- 
1.6.5.2


_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux