hp_accel: do not call ACPI from invalid context
[safe/jmp/linux-2.6] / drivers / hwmon / w83627ehf.c
index e3dfc52..cb808d0 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 #include "lm75.h"
 
@@ -59,6 +60,10 @@ static const char * w83627ehf_device_names[] = {
        "w83627dhg",
 };
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 #define DRVNAME "w83627ehf"
 
 /*
@@ -256,7 +261,7 @@ struct w83627ehf_data {
        int addr;       /* IO base of hw monitor block */
        const char *name;
 
-       struct class_device *class_dev;
+       struct device *hwmon_dev;
        struct mutex lock;
 
        struct mutex update_lock;
@@ -498,7 +503,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
                }
 
                for (i = 0; i < 4; i++) {
-                       /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
+                       /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
                        if (i != 1) {
                                pwmcfg = w83627ehf_read_value(data,
                                                W83627EHF_REG_PWM_ENABLE[i]);
@@ -1198,8 +1203,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
                device_remove_file(dev, &sda_temp[i].dev_attr);
 
        device_remove_file(dev, &dev_attr_name);
-       if (data->vid != 0x3f)
-               device_remove_file(dev, &dev_attr_cpu0_vid);
+       device_remove_file(dev, &dev_attr_cpu0_vid);
 }
 
 /* Get the monitoring functions started */
@@ -1276,26 +1280,39 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 
        data->vrm = vid_which_vrm();
        superio_enter(sio_data->sioreg);
-       /* Set VID input sensibility if needed. In theory the BIOS should
-          have set it, but in practice it's not always the case. */
-       en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10);
-       if ((en_vrm10 & 0x08) && data->vrm != 100) {
-               dev_warn(dev, "Setting VID input voltage to TTL\n");
-               superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
-                            en_vrm10 & ~0x08);
-       } else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
-               dev_warn(dev, "Setting VID input voltage to VRM10\n");
-               superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
-                            en_vrm10 | 0x08);
-       }
        /* Read VID value */
        superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
-       if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80)
-               data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f;
-       else {
+       if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
+               /* Set VID input sensibility if needed. In theory the BIOS
+                  should have set it, but in practice it's not always the
+                  case. We only do it for the W83627EHF/EHG because the
+                  W83627DHG is more complex in this respect. */
+               if (sio_data->kind == w83627ehf) {
+                       en_vrm10 = superio_inb(sio_data->sioreg,
+                                              SIO_REG_EN_VRM10);
+                       if ((en_vrm10 & 0x08) && data->vrm == 90) {
+                               dev_warn(dev, "Setting VID input voltage to "
+                                        "TTL\n");
+                               superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
+                                            en_vrm10 & ~0x08);
+                       } else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
+                               dev_warn(dev, "Setting VID input voltage to "
+                                        "VRM10\n");
+                               superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
+                                            en_vrm10 | 0x08);
+                       }
+               }
+
+               data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA);
+               if (sio_data->kind == w83627ehf) /* 6 VID pins only */
+                       data->vid &= 0x3f;
+
+               err = device_create_file(dev, &dev_attr_cpu0_vid);
+               if (err)
+                       goto exit_release;
+       } else {
                dev_info(dev, "VID pins in output mode, CPU VID not "
                         "available\n");
-               data->vid = 0x3f;
        }
 
        /* fan4 and fan5 share some pins with the GPIO and serial flash */
@@ -1378,15 +1395,9 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
        if (err)
                goto exit_remove;
 
-       if (data->vid != 0x3f) {
-               err = device_create_file(dev, &dev_attr_cpu0_vid);
-               if (err)
-                       goto exit_remove;
-       }
-
-       data->class_dev = hwmon_device_register(dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       data->hwmon_dev = hwmon_device_register(dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
                goto exit_remove;
        }
 
@@ -1406,7 +1417,7 @@ static int __devexit w83627ehf_remove(struct platform_device *pdev)
 {
        struct w83627ehf_data *data = platform_get_drvdata(pdev);
 
-       hwmon_device_unregister(data->class_dev);
+       hwmon_device_unregister(data->hwmon_dev);
        w83627ehf_device_remove_files(&pdev->dev);
        release_region(data->addr, IOREGION_LENGTH);
        platform_set_drvdata(pdev, NULL);
@@ -1437,8 +1448,11 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
 
        superio_enter(sioaddr);
 
-       val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
-           | superio_inb(sioaddr, SIO_REG_DEVID + 1);
+       if (force_id)
+               val = force_id;
+       else
+               val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
+                   | superio_inb(sioaddr, SIO_REG_DEVID + 1);
        switch (val & SIO_ID_MASK) {
        case SIO_W83627EHF_ID:
                sio_data->kind = w83627ehf;
@@ -1531,6 +1545,11 @@ static int __init sensors_w83627ehf_init(void)
        res.start = address + IOREGION_OFFSET;
        res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
        res.flags = IORESOURCE_IO;
+
+       err = acpi_check_resource_conflict(&res);
+       if (err)
+               goto exit;
+
        err = platform_device_add_resources(pdev, &res, 1);
        if (err) {
                printk(KERN_ERR DRVNAME ": Device resource addition failed "