Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
Linus Torvalds [Mon, 11 Jan 2010 17:45:55 +0000 (09:45 -0800)]
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  hwmon: Make PCI device ids constant
  hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs
  hwmon: (k10temp) Blacklist more family 10h processors
  hwmon: (asus_atk0110) Add debugfs interface
  hwmon: (asus_atk0110) Refactor interface probe code
  hwmon: (adt7462) Fix pin 28 monitoring

Documentation/hwmon/k10temp
drivers/hwmon/Kconfig
drivers/hwmon/adt7462.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/coretemp.c
drivers/hwmon/k10temp.c
drivers/hwmon/k8temp.c
drivers/hwmon/sis5595.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c

index a7a18d4..6526eee 100644 (file)
@@ -3,8 +3,8 @@ Kernel driver k10temp
 
 Supported chips:
 * AMD Family 10h processors:
-  Socket F: Quad-Core/Six-Core/Embedded Opteron
-  Socket AM2+: Opteron, Phenom (II) X3/X4
+  Socket F: Quad-Core/Six-Core/Embedded Opteron (but see below)
+  Socket AM2+: Quad-Core Opteron, Phenom (II) X3/X4, Athlon X2 (but see below)
   Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
   Socket S1G3: Athlon II, Sempron, Turion II
 * AMD Family 11h processors:
@@ -36,10 +36,15 @@ Description
 This driver permits reading of the internal temperature sensor of AMD
 Family 10h and 11h processors.
 
-All these processors have a sensor, but on older revisions of Family 10h
-processors, the sensor may return inconsistent values (erratum 319). The
-driver will refuse to load on these revisions unless you specify the
-"force=1" module parameter.
+All these processors have a sensor, but on those for Socket F or AM2+,
+the sensor may return inconsistent values (erratum 319).  The driver
+will refuse to load on these revisions unless you specify the "force=1"
+module parameter.
+
+Due to technical reasons, the driver can detect only the mainboard's
+socket type, not the processor's actual capabilities.  Therefore, if you
+are using an AM3 processor on an AM2+ mainboard, you can safely use the
+"force=1" parameter.
 
 There is one temperature measurement value, available as temp1_input in
 sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
index 07a0f03..68cf877 100644 (file)
@@ -392,7 +392,7 @@ config SENSORS_GL520SM
 
 config SENSORS_CORETEMP
        tristate "Intel Core/Core2/Atom temperature sensor"
-       depends on X86 && EXPERIMENTAL
+       depends on X86 && PCI && EXPERIMENTAL
        help
          If you say yes here you get support for the temperature
          sensor inside your CPU. Most of the family 6 CPUs
index a1a7ef1..a31e77c 100644 (file)
@@ -94,7 +94,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
 #define                ADT7462_PIN24_SHIFT             6
 #define                ADT7462_PIN26_VOLT_INPUT        0x08
 #define                ADT7462_PIN25_VOLT_INPUT        0x20
-#define                ADT7462_PIN28_SHIFT             6       /* cfg3 */
+#define                ADT7462_PIN28_SHIFT             4       /* cfg3 */
 #define                ADT7462_PIN28_VOLT              0x5
 
 #define ADT7462_REG_ALARM1                     0xB8
index 5a3ee00..6811346 100644 (file)
@@ -5,6 +5,7 @@
  * See COPYING in the top level directory of the kernel tree.
  */
 
+#include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/hwmon.h>
 #include <linux/list.h>
@@ -101,6 +102,11 @@ struct atk_data {
        int temperature_count;
        int fan_count;
        struct list_head sensor_list;
+
+       struct {
+               struct dentry *root;
+               u32 id;
+       } debugfs;
 };
 
 
@@ -624,6 +630,187 @@ static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
        return err;
 }
 
+#ifdef CONFIG_DEBUG_FS
+static int atk_debugfs_gitm_get(void *p, u64 *val)
+{
+       struct atk_data *data = p;
+       union acpi_object *ret;
+       struct atk_acpi_ret_buffer *buf;
+       int err = 0;
+
+       if (!data->read_handle)
+               return -ENODEV;
+
+       if (!data->debugfs.id)
+               return -EINVAL;
+
+       ret = atk_gitm(data, data->debugfs.id);
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       buf = (struct atk_acpi_ret_buffer *)ret->buffer.pointer;
+       if (buf->flags)
+               *val = buf->value;
+       else
+               err = -EIO;
+
+       return err;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm,
+                       atk_debugfs_gitm_get,
+                       NULL,
+                       "0x%08llx\n")
+
+static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj)
+{
+       int ret = 0;
+
+       switch (obj->type) {
+       case ACPI_TYPE_INTEGER:
+               ret = snprintf(buf, sz, "0x%08llx\n", obj->integer.value);
+               break;
+       case ACPI_TYPE_STRING:
+               ret = snprintf(buf, sz, "%s\n", obj->string.pointer);
+               break;
+       }
+
+       return ret;
+}
+
+static void atk_pack_print(char *buf, size_t sz, union acpi_object *pack)
+{
+       int ret;
+       int i;
+
+       for (i = 0; i < pack->package.count; i++) {
+               union acpi_object *obj = &pack->package.elements[i];
+
+               ret = atk_acpi_print(buf, sz, obj);
+               if (ret >= sz)
+                       break;
+               buf += ret;
+               sz -= ret;
+       }
+}
+
+static int atk_debugfs_ggrp_open(struct inode *inode, struct file *file)
+{
+       struct atk_data *data = inode->i_private;
+       char *buf = NULL;
+       union acpi_object *ret;
+       u8 cls;
+       int i;
+
+       if (!data->enumerate_handle)
+               return -ENODEV;
+       if (!data->debugfs.id)
+               return -EINVAL;
+
+       cls = (data->debugfs.id & 0xff000000) >> 24;
+       ret = atk_ggrp(data, cls);
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       for (i = 0; i < ret->package.count; i++) {
+               union acpi_object *pack = &ret->package.elements[i];
+               union acpi_object *id;
+
+               if (pack->type != ACPI_TYPE_PACKAGE)
+                       continue;
+               if (!pack->package.count)
+                       continue;
+               id = &pack->package.elements[0];
+               if (id->integer.value == data->debugfs.id) {
+                       /* Print the package */
+                       buf = kzalloc(512, GFP_KERNEL);
+                       if (!buf) {
+                               ACPI_FREE(ret);
+                               return -ENOMEM;
+                       }
+                       atk_pack_print(buf, 512, pack);
+                       break;
+               }
+       }
+       ACPI_FREE(ret);
+
+       if (!buf)
+               return -EINVAL;
+
+       file->private_data = buf;
+
+       return nonseekable_open(inode, file);
+}
+
+static ssize_t atk_debugfs_ggrp_read(struct file *file, char __user *buf,
+               size_t count, loff_t *pos)
+{
+       char *str = file->private_data;
+       size_t len = strlen(str);
+
+       return simple_read_from_buffer(buf, count, pos, str, len);
+}
+
+static int atk_debugfs_ggrp_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+static const struct file_operations atk_debugfs_ggrp_fops = {
+       .read           = atk_debugfs_ggrp_read,
+       .open           = atk_debugfs_ggrp_open,
+       .release        = atk_debugfs_ggrp_release,
+};
+
+static void atk_debugfs_init(struct atk_data *data)
+{
+       struct dentry *d;
+       struct dentry *f;
+
+       data->debugfs.id = 0;
+
+       d = debugfs_create_dir("asus_atk0110", NULL);
+       if (!d || IS_ERR(d))
+               return;
+
+       f = debugfs_create_x32("id", S_IRUSR | S_IWUSR, d, &data->debugfs.id);
+       if (!f || IS_ERR(f))
+               goto cleanup;
+
+       f = debugfs_create_file("gitm", S_IRUSR, d, data,
+                       &atk_debugfs_gitm);
+       if (!f || IS_ERR(f))
+               goto cleanup;
+
+       f = debugfs_create_file("ggrp", S_IRUSR, d, data,
+                       &atk_debugfs_ggrp_fops);
+       if (!f || IS_ERR(f))
+               goto cleanup;
+
+       data->debugfs.root = d;
+
+       return;
+cleanup:
+       debugfs_remove_recursive(d);
+}
+
+static void atk_debugfs_cleanup(struct atk_data *data)
+{
+       debugfs_remove_recursive(data->debugfs.root);
+}
+
+#else /* CONFIG_DEBUG_FS */
+
+static void atk_debugfs_init(struct atk_data *data)
+{
+}
+
+static void atk_debugfs_cleanup(struct atk_data *data)
+{
+}
+#endif
+
 static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
 {
        struct device *dev = &data->acpi_dev->dev;
@@ -1047,76 +1234,75 @@ remove:
        return err;
 }
 
-static int atk_check_old_if(struct atk_data *data)
+static int atk_probe_if(struct atk_data *data)
 {
        struct device *dev = &data->acpi_dev->dev;
        acpi_handle ret;
        acpi_status status;
+       int err = 0;
 
        /* RTMP: read temperature */
        status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->rtmp_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->rtmp_handle = ret;
 
        /* RVLT: read voltage */
        status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->rvlt_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->rvlt_handle = ret;
 
        /* RFAN: read fan status */
        status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->rfan_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->rfan_handle = ret;
-
-       return 0;
-}
-
-static int atk_check_new_if(struct atk_data *data)
-{
-       struct device *dev = &data->acpi_dev->dev;
-       acpi_handle ret;
-       acpi_status status;
 
        /* Enumeration */
        status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->enumerate_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->enumerate_handle = ret;
 
        /* De-multiplexer (read) */
        status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret);
-       if (status != AE_OK) {
+       if (ACPI_SUCCESS(status))
+               data->read_handle = ret;
+       else
                dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
                                acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->read_handle = ret;
 
        /* De-multiplexer (write) */
        status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
-       if (status != AE_OK) {
-               dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
+       if (ACPI_SUCCESS(status))
+               data->write_handle = ret;
+       else
+               dev_dbg(dev, "method " METHOD_WRITE " not found: %s\n",
                                 acpi_format_exception(status));
-               return -ENODEV;
-       }
-       data->write_handle = ret;
 
-       return 0;
+       /* Check for hwmon methods: first check "old" style methods; note that
+        * both may be present: in this case we stick to the old interface;
+        * analysis of multiple DSDTs indicates that when both interfaces
+        * are present the new one (GGRP/GITM) is not functional.
+        */
+       if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle)
+               data->old_interface = true;
+       else if (data->enumerate_handle && data->read_handle &&
+                       data->write_handle)
+               data->old_interface = false;
+       else
+               err = -ENODEV;
+
+       return err;
 }
 
 static int atk_add(struct acpi_device *device)
@@ -1155,28 +1341,19 @@ static int atk_add(struct acpi_device *device)
        }
        ACPI_FREE(buf.pointer);
 
-       /* Check for hwmon methods: first check "old" style methods; note that
-        * both may be present: in this case we stick to the old interface;
-        * analysis of multiple DSDTs indicates that when both interfaces
-        * are present the new one (GGRP/GITM) is not functional.
-        */
-       err = atk_check_old_if(data);
-       if (!err) {
-               dev_dbg(&device->dev, "Using old hwmon interface\n");
-               data->old_interface = true;
-       } else {
-               err = atk_check_new_if(data);
-               if (err)
-                       goto out;
-
-               dev_dbg(&device->dev, "Using new hwmon interface\n");
-               data->old_interface = false;
+       err = atk_probe_if(data);
+       if (err) {
+               dev_err(&device->dev, "No usable hwmon interface detected\n");
+               goto out;
        }
 
-       if (data->old_interface)
+       if (data->old_interface) {
+               dev_dbg(&device->dev, "Using old hwmon interface\n");
                err = atk_enumerate_old_hwmon(data);
-       else
+       } else {
+               dev_dbg(&device->dev, "Using new hwmon interface\n");
                err = atk_enumerate_new_hwmon(data);
+       }
        if (err < 0)
                goto out;
        if (err == 0) {
@@ -1190,6 +1367,8 @@ static int atk_add(struct acpi_device *device)
        if (err)
                goto cleanup;
 
+       atk_debugfs_init(data);
+
        device->driver_data = data;
        return 0;
 cleanup:
@@ -1208,6 +1387,8 @@ static int atk_remove(struct acpi_device *device, int type)
 
        device->driver_data = NULL;
 
+       atk_debugfs_cleanup(data);
+
        atk_remove_files(data);
        atk_free_sensors(data);
        hwmon_device_unregister(data->hwmon_dev);
index caef39c..2d7bcee 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
+#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
@@ -161,6 +162,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
        int usemsr_ee = 1;
        int err;
        u32 eax, edx;
+       struct pci_dev *host_bridge;
 
        /* Early chips have no MSR for TjMax */
 
@@ -168,11 +170,21 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
                usemsr_ee = 0;
        }
 
-       /* Atoms seems to have TjMax at 90C */
+       /* Atom CPUs */
 
        if (c->x86_model == 0x1c) {
                usemsr_ee = 0;
-               tjmax = 90000;
+
+               host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+
+               if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
+                   && (host_bridge->device == 0xa000   /* NM10 based nettop */
+                   || host_bridge->device == 0xa010))  /* NM10 based netbook */
+                       tjmax = 100000;
+               else
+                       tjmax = 90000;
+
+               pci_dev_put(host_bridge);
        }
 
        if ((c->x86_model > 0xe) && (usemsr_ee)) {
index d8a26d1..099a213 100644 (file)
@@ -33,6 +33,16 @@ static bool force;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
 
+/* CPUID function 0x80000001, ebx */
+#define CPUID_PKGTYPE_MASK     0xf0000000
+#define CPUID_PKGTYPE_F                0x00000000
+#define CPUID_PKGTYPE_AM2R2_AM3        0x10000000
+
+/* DRAM controller (PCI function 2) */
+#define REG_DCT0_CONFIG_HIGH           0x094
+#define  DDR3_MODE                     0x00000100
+
+/* miscellaneous (PCI function 3) */
 #define REG_HARDWARE_THERMAL_CONTROL   0x64
 #define  HTC_ENABLE                    0x00000001
 
@@ -85,13 +95,28 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static bool __devinit has_erratum_319(void)
+static bool __devinit has_erratum_319(struct pci_dev *pdev)
 {
+       u32 pkg_type, reg_dram_cfg;
+
+       if (boot_cpu_data.x86 != 0x10)
+               return false;
+
        /*
-        * Erratum 319: The thermal sensor of older Family 10h processors
-        *              (B steppings) may be unreliable.
+        * Erratum 319: The thermal sensor of Socket F/AM2+ processors
+        *              may be unreliable.
         */
-       return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2;
+       pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK;
+       if (pkg_type == CPUID_PKGTYPE_F)
+               return true;
+       if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
+               return false;
+
+       /* Differentiate between AM2+ (bad) and AM3 (good) */
+       pci_bus_read_config_dword(pdev->bus,
+                                 PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
+                                 REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
+       return !(reg_dram_cfg & DDR3_MODE);
 }
 
 static int __devinit k10temp_probe(struct pci_dev *pdev,
@@ -99,9 +124,10 @@ static int __devinit k10temp_probe(struct pci_dev *pdev,
 {
        struct device *hwmon_dev;
        u32 reg_caps, reg_htc;
+       int unreliable = has_erratum_319(pdev);
        int err;
 
-       if (has_erratum_319() && !force) {
+       if (unreliable && !force) {
                dev_err(&pdev->dev,
                        "unreliable CPU thermal sensor; monitoring disabled\n");
                err = -ENODEV;
@@ -139,7 +165,7 @@ static int __devinit k10temp_probe(struct pci_dev *pdev,
        }
        dev_set_drvdata(&pdev->dev, hwmon_dev);
 
-       if (has_erratum_319() && force)
+       if (unreliable && force)
                dev_warn(&pdev->dev,
                         "unreliable CPU thermal sensor; check erratum 319\n");
        return 0;
@@ -169,7 +195,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)
        dev_set_drvdata(&pdev->dev, NULL);
 }
 
-static struct pci_device_id k10temp_id_table[] = {
+static const struct pci_device_id k10temp_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        {}
index 1fe9951..0ceb6d6 100644 (file)
@@ -136,7 +136,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static struct pci_device_id k8temp_ids[] = {
+static const struct pci_device_id k8temp_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { 0 },
 };
index 12f2e70..79c2931 100644 (file)
@@ -697,7 +697,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
        return data;
 }
 
-static struct pci_device_id sis5595_pci_ids[] = {
+static const struct pci_device_id sis5595_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
        { 0, }
 };
index 39e82a4..f397ce7 100644 (file)
@@ -767,7 +767,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
        return data;
 }
 
-static struct pci_device_id via686a_pci_ids[] = {
+static const struct pci_device_id via686a_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
        { 0, }
 };
index 470a122..d47b4c9 100644 (file)
@@ -697,7 +697,7 @@ static struct platform_driver vt8231_driver = {
        .remove = __devexit_p(vt8231_remove),
 };
 
-static struct pci_device_id vt8231_pci_ids[] = {
+static const struct pci_device_id vt8231_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
        { 0, }
 };