Patch[RFC]:Merging_Pkgtemp_with_Coretemp

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

 



Hi,

Here is the much awaited patch to merge pkgtemp with coretemp.

This patch creates the pkgtemp interfaces under the same
hwmonX/device directory as that of the coretemp. None of the
coretemp interfaces names are changed(for compatibility reasons).

I am working on merging/adding documentation on the same.
Would like to receive initial review comments, so that I can add
final documentation once the code is somewhat acceptable.

-----------------------------
From: Durgadoss R <durgadoss.r@xxxxxxxxx>

Date: Tue, 8 Feb 2011 04:21:14 +0530
Subject: PATCH[RFC] Merging_Pkgtemp_with_Coretemp

This patch merges the pkgtemp driver with the coretemp driver.

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