hwmon: (coretemp) constify static data
[pandora-kernel.git] / drivers / hwmon / coretemp.c
index 4112576..ac1c81f 100644 (file)
 #include <linux/cpu.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
+#include <linux/moduleparam.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
 #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 NUM_REAL_CORES         16      /* Number of Real cores per cpu */
 #define CORETEMP_NAME_LENGTH   17      /* String Length of 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 TOTAL_ATTRS            (MAX_CORE_ATTRS + 1)
 #define MAX_CORE_DATA          (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
 
 #ifdef CONFIG_SMP
@@ -69,8 +77,6 @@
  *             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.
 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;
@@ -143,19 +147,6 @@ 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_STATUS_THRESHOLD1));
-}
-
 static ssize_t show_tjmax(struct device *dev,
                        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);
 }
 
-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,
                        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)
 {
-       /* The 100C is default for both mobile and non mobile CPUs */
        int err;
        u32 eax, edx;
        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);
        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 {
                val = (eax >> 16) & 0xff;
                /*
@@ -393,11 +307,17 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
                 * will be used
                 */
                if (val) {
-                       dev_info(dev, "TjMax is %d C.\n", val);
+                       dev_dbg(dev, "TjMax is %d degrees C\n", val);
                        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.
         * 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);
 }
 
-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)
 {
        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 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) = {
                        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] = {
+                       show_ttarget };
+       static const char *const names[TOTAL_ATTRS] = {
                                        "temp%d_label", "temp%d_crit_alarm",
                                        "temp%d_input", "temp%d_crit",
-                                       "temp%d_max_alarm", "temp%d_max",
-                                       "temp%d_max_hyst" };
+                                       "temp%d_max" };
 
        for (i = 0; i < tdata->attr_size; 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);
                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.store = rw_ptr[i];
-               }
                tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
                tdata->sd_attrs[i].index = attr_no;
                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 :
                                                        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);
@@ -588,25 +482,21 @@ static int create_core_data(struct platform_data *pdata,
                goto exit_free;
 
        /* We can access status register. Get Critical Temperature */
-       if (pkg_flag)
-               tdata->tjmax = get_pkg_tjmax(pdev->id, &pdev->dev);
-       else
-               tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
+       tdata->tjmax = get_tjmax(c, cpu, &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
+        * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET.
+        * The target temperature is available on older CPUs but not in this
+        * register. Atoms don't have the register at all.
         */
-       err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx);
-       if (!err) {
-               tdata->attr_size += MAX_THRESH_ATTRS;
-               tdata->tmin = tdata->tjmax -
-                             ((eax & THERM_MASK_THRESHOLD0) >>
-                              THERM_SHIFT_THRESHOLD0) * 1000;
-               tdata->ttarget = tdata->tjmax -
-                                ((eax & THERM_MASK_THRESHOLD1) >>
-                                 THERM_SHIFT_THRESHOLD1) * 1000;
+       if (c->x86_model > 0xe && c->x86_model != 0x1c) {
+               err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET,
+                                       &eax, &edx);
+               if (!err) {
+                       tdata->ttarget
+                         = tdata->tjmax - ((eax >> 8) & 0xff) * 1000;
+                       tdata->attr_size++;
+               }
        }
 
        pdata->core_data[attr_no] = tdata;
@@ -671,7 +561,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
        if (err)
                goto exit_free;
 
-       pdata->phys_proc_id = TO_PHYS_ID(pdev->id);
+       pdata->phys_proc_id = pdev->id;
        platform_set_drvdata(pdev, pdata);
 
        pdata->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -723,7 +613,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
 
        mutex_lock(&pdev_list_mutex);
 
-       pdev = platform_device_alloc(DRVNAME, cpu);
+       pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu));
        if (!pdev) {
                err = -ENOMEM;
                pr_err("Device allocation failed\n");