lis3lv02d: correct memory leak in module unload
[safe/jmp/linux-2.6] / drivers / hwmon / abituguru.c
index cc15c4f..03694cc 100644 (file)
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 /*
-    This driver supports the sensor part of the custom Abit uGuru chip found
-    on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM /
-    etc voltage & frequency control is not supported!
+    This driver supports the sensor part of the first and second revision of
+    the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because
+    of lack of specs the CPU/RAM voltage & frequency control is not supported!
 */
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <asm/io.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
 
 /* Banks */
 #define ABIT_UGURU_ALARM_BANK                  0x20 /* 1x 3 bytes */
 #define ABIT_UGURU_IN_SENSOR                   0
 #define ABIT_UGURU_TEMP_SENSOR                 1
 #define ABIT_UGURU_NC                          2
-/* Timeouts / Retries, if these turn out to need a lot of fiddling we could
-   convert them to params. */
-/* 250 was determined by trial and error, 200 works most of the time, but not
-   always. I assume this is cpu-speed independent, since the ISA-bus and not
-   the CPU should be the bottleneck. Note that 250 sometimes is still not
-   enough (only reported on AN7 mb) this is handled by a higher layer. */
-#define ABIT_UGURU_WAIT_TIMEOUT                        250
+/* In many cases we need to wait for the uGuru to reach a certain status, most
+   of the time it will reach this status within 30 - 90 ISA reads, and thus we
+   can best busy wait. This define gives the total amount of reads to try. */
+#define ABIT_UGURU_WAIT_TIMEOUT                        125
+/* However sometimes older versions of the uGuru seem to be distracted and they
+   do not respond for a long time. To handle this we sleep before each of the
+   last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. */
+#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP          5
 /* Normally all expected status in abituguru_ready, are reported after the
-   first read, but sometimes not and we need to poll, 5 polls was not enough
-   50 sofar is. */
-#define ABIT_UGURU_READY_TIMEOUT               50
+   first read, but sometimes not and we need to poll. */
+#define ABIT_UGURU_READY_TIMEOUT               5
 /* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */
 #define ABIT_UGURU_MAX_RETRIES                 3
 #define ABIT_UGURU_RETRY_DELAY                 (HZ/5)
@@ -173,7 +176,7 @@ MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n"
    The structure is dynamically allocated, at the same time when a new
    abituguru device is allocated. */
 struct abituguru_data {
-       struct class_device *class_dev; /* hwmon registered device */
+       struct device *hwmon_dev;       /* hwmon registered device */
        struct mutex update_lock;       /* protect access to data and uGuru */
        unsigned long last_updated;     /* In jiffies */
        unsigned short addr;            /* uguru base address */
@@ -226,6 +229,10 @@ static int abituguru_wait(struct abituguru_data *data, u8 state)
                timeout--;
                if (timeout == 0)
                        return -EBUSY;
+               /* sleep a bit before our last few tries, see the comment on
+                  this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. */
+               if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP)
+                       msleep(0);
        }
        return 0;
 }
@@ -256,6 +263,7 @@ static int abituguru_ready(struct abituguru_data *data)
                           "CMD reg does not hold 0xAC after ready command\n");
                        return -EIO;
                }
+               msleep(0);
        }
 
        /* After this the ABIT_UGURU_DATA port should contain
@@ -268,6 +276,7 @@ static int abituguru_ready(struct abituguru_data *data)
                                "state != more input after ready command\n");
                        return -EIO;
                }
+               msleep(0);
        }
 
        data->uguru_ready = 1;
@@ -331,7 +340,8 @@ static int abituguru_read(struct abituguru_data *data,
        /* And read the data */
        for (i = 0; i < count; i++) {
                if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
-                       ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for "
+                       ABIT_UGURU_DEBUG(retries ? 1 : 3,
+                               "timeout exceeded waiting for "
                                "read state (bank: %d, sensor: %d)\n",
                                (int)bank_addr, (int)sensor_addr);
                        break;
@@ -350,7 +360,9 @@ static int abituguru_read(struct abituguru_data *data,
 static int abituguru_write(struct abituguru_data *data,
        u8 bank_addr, u8 sensor_addr, u8 *buf, int count)
 {
-       int i;
+       /* We use the ready timeout as we have to wait for 0xAC just like the
+          ready function */
+       int i, timeout = ABIT_UGURU_READY_TIMEOUT;
 
        /* Send the address */
        i = abituguru_send_address(data, bank_addr, sensor_addr,
@@ -370,7 +382,8 @@ static int abituguru_write(struct abituguru_data *data,
        }
 
        /* Now we need to wait till the chip is ready to be read again,
-          don't ask why */
+          so that we can read 0xAC as confirmation that our write has
+          succeeded. */
        if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
                ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state "
                        "after write (bank: %d, sensor: %d)\n", (int)bank_addr,
@@ -379,11 +392,15 @@ static int abituguru_write(struct abituguru_data *data,
        }
 
        /* Cmd port MUST be read now and should contain 0xAC */
-       if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
-               ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write "
-                       "(bank: %d, sensor: %d)\n", (int)bank_addr,
-                       (int)sensor_addr);
-               return -EIO;
+       while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+               timeout--;
+               if (timeout == 0) {
+                       ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after "
+                               "write (bank: %d, sensor: %d)\n",
+                               (int)bank_addr, (int)sensor_addr);
+                       return -EIO;
+               }
+               msleep(0);
        }
 
        /* Last put the chip back in ready state */
@@ -402,8 +419,8 @@ static int __devinit
 abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
                                   u8 sensor_addr)
 {
-       u8 val, buf[3];
-       int ret = ABIT_UGURU_NC;
+       u8 val, test_flag, buf[3];
+       int i, ret = -ENODEV; /* error is the most common used retval :| */
 
        /* If overriden by the user return the user selected type */
        if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR &&
@@ -420,7 +437,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
                return -ENODEV;
 
        /* Test val is sane / usable for sensor type detection. */
-       if ((val < 10u) || (val > 240u)) {
+       if ((val < 10u) || (val > 250u)) {
                printk(KERN_WARNING ABIT_UGURU_NAME
                        ": bank1-sensor: %d reading (%d) too close to limits, "
                        "unable to determine sensor type, skipping sensor\n",
@@ -433,13 +450,23 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
 
        ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
        /* Volt sensor test, enable volt low alarm, set min value ridicously
-          high. If its a volt sensor this should always give us an alarm. */
-       buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE;
-       buf[1] = 245;
-       buf[2] = 250;
+          high, or vica versa if the reading is very high. If its a volt
+          sensor this should always give us an alarm. */
+       if (val <= 240u) {
+               buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE;
+               buf[1] = 245;
+               buf[2] = 250;
+               test_flag = ABIT_UGURU_VOLT_LOW_ALARM_FLAG;
+       } else {
+               buf[0] = ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE;
+               buf[1] = 5;
+               buf[2] = 10;
+               test_flag = ABIT_UGURU_VOLT_HIGH_ALARM_FLAG;
+       }
+
        if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
                        buf, 3) != 3)
-               return -ENODEV;
+               goto abituguru_detect_bank1_sensor_type_exit;
        /* Now we need 20 ms to give the uguru time to read the sensors
           and raise a voltage alarm */
        set_current_state(TASK_UNINTERRUPTIBLE);
@@ -447,24 +474,19 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
        /* Check for alarm and check the alarm is a volt low alarm. */
        if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
                        ABIT_UGURU_MAX_RETRIES) != 3)
-               return -ENODEV;
+               goto abituguru_detect_bank1_sensor_type_exit;
        if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
                if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
                                sensor_addr, buf, 3,
                                ABIT_UGURU_MAX_RETRIES) != 3)
-                       return -ENODEV;
-               if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) {
-                       /* Restore original settings */
-                       if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
-                                       sensor_addr,
-                                       data->bank1_settings[sensor_addr],
-                                       3) != 3)
-                               return -ENODEV;
+                       goto abituguru_detect_bank1_sensor_type_exit;
+               if (buf[0] & test_flag) {
                        ABIT_UGURU_DEBUG(2, "  found volt sensor\n");
-                       return ABIT_UGURU_IN_SENSOR;
+                       ret = ABIT_UGURU_IN_SENSOR;
+                       goto abituguru_detect_bank1_sensor_type_exit;
                } else
                        ABIT_UGURU_DEBUG(2, "  alarm raised during volt "
-                               "sensor test, but volt low flag not set\n");
+                               "sensor test, but volt range flag not set\n");
        } else
                ABIT_UGURU_DEBUG(2, "  alarm not raised during volt sensor "
                        "test\n");
@@ -477,7 +499,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
        buf[2] = 10;
        if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
                        buf, 3) != 3)
-               return -ENODEV;
+               goto abituguru_detect_bank1_sensor_type_exit;
        /* Now we need 50 ms to give the uguru time to read the sensors
           and raise a temp alarm */
        set_current_state(TASK_UNINTERRUPTIBLE);
@@ -485,15 +507,16 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
        /* Check for alarm and check the alarm is a temp high alarm. */
        if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
                        ABIT_UGURU_MAX_RETRIES) != 3)
-               return -ENODEV;
+               goto abituguru_detect_bank1_sensor_type_exit;
        if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
                if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
                                sensor_addr, buf, 3,
                                ABIT_UGURU_MAX_RETRIES) != 3)
-                       return -ENODEV;
+                       goto abituguru_detect_bank1_sensor_type_exit;
                if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) {
-                       ret = ABIT_UGURU_TEMP_SENSOR;
                        ABIT_UGURU_DEBUG(2, "  found temp sensor\n");
+                       ret = ABIT_UGURU_TEMP_SENSOR;
+                       goto abituguru_detect_bank1_sensor_type_exit;
                } else
                        ABIT_UGURU_DEBUG(2, "  alarm raised during temp "
                                "sensor test, but temp high flag not set\n");
@@ -501,11 +524,23 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
                ABIT_UGURU_DEBUG(2, "  alarm not raised during temp sensor "
                        "test\n");
 
-       /* Restore original settings */
-       if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
-                       data->bank1_settings[sensor_addr], 3) != 3)
+       ret = ABIT_UGURU_NC;
+abituguru_detect_bank1_sensor_type_exit:
+       /* Restore original settings, failing here is really BAD, it has been
+          reported that some BIOS-es hang when entering the uGuru menu with
+          invalid settings present in the uGuru, so we try this 3 times. */
+       for (i = 0; i < 3; i++)
+               if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+                               sensor_addr, data->bank1_settings[sensor_addr],
+                               3) == 3)
+                       break;
+       if (i == 3) {
+               printk(KERN_ERR ABIT_UGURU_NAME
+                       ": Fatal error could not restore original settings. "
+                       "This should never happen please report this to the "
+                       "abituguru maintainer (see MAINTAINERS)\n");
                return -ENODEV;
-
+       }
        return ret;
 }
 
@@ -1243,30 +1278,43 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
        printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
 
        /* Register sysfs hooks */
-       data->class_dev = hwmon_device_register(&pdev->dev);
-       if (IS_ERR(data->class_dev)) {
-               res = PTR_ERR(data->class_dev);
-               goto abituguru_probe_error;
-       }
        for (i = 0; i < sysfs_attr_i; i++)
-               device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+               if (device_create_file(&pdev->dev,
+                               &data->sysfs_attr[i].dev_attr))
+                       goto abituguru_probe_error;
        for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
-               device_create_file(&pdev->dev,
-                       &abituguru_sysfs_attr[i].dev_attr);
+               if (device_create_file(&pdev->dev,
+                               &abituguru_sysfs_attr[i].dev_attr))
+                       goto abituguru_probe_error;
 
-       return 0;
+       data->hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (!IS_ERR(data->hwmon_dev))
+               return 0; /* success */
 
+       res = PTR_ERR(data->hwmon_dev);
 abituguru_probe_error:
+       for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
+               device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+       for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
+               device_remove_file(&pdev->dev,
+                       &abituguru_sysfs_attr[i].dev_attr);
+       platform_set_drvdata(pdev, NULL);
        kfree(data);
        return res;
 }
 
 static int __devexit abituguru_remove(struct platform_device *pdev)
 {
+       int i;
        struct abituguru_data *data = platform_get_drvdata(pdev);
 
+       hwmon_device_unregister(data->hwmon_dev);
+       for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
+               device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+       for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
+               device_remove_file(&pdev->dev,
+                       &abituguru_sysfs_attr[i].dev_attr);
        platform_set_drvdata(pdev, NULL);
-       hwmon_device_unregister(data->class_dev);
        kfree(data);
 
        return 0;
@@ -1305,7 +1353,7 @@ static struct abituguru_data *abituguru_update_device(struct device *dev)
                data->update_timeouts = 0;
 LEAVE_UPDATE:
                /* handle timeout condition */
-               if (err == -EBUSY) {
+               if (!success && (err == -EBUSY || err >= 0)) {
                        /* No overflow please */
                        if (data->update_timeouts < 255u)
                                data->update_timeouts++;
@@ -1331,13 +1379,39 @@ LEAVE_UPDATE:
                return NULL;
 }
 
+#ifdef CONFIG_PM
+static int abituguru_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct abituguru_data *data = platform_get_drvdata(pdev);
+       /* make sure all communications with the uguru are done and no new
+          ones are started */
+       mutex_lock(&data->update_lock);
+       return 0;
+}
+
+static int abituguru_resume(struct platform_device *pdev)
+{
+       struct abituguru_data *data = platform_get_drvdata(pdev);
+       /* See if the uGuru is still ready */
+       if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT)
+               data->uguru_ready = 0;
+       mutex_unlock(&data->update_lock);
+       return 0;
+}
+#else
+#define abituguru_suspend      NULL
+#define abituguru_resume       NULL
+#endif /* CONFIG_PM */
+
 static struct platform_driver abituguru_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = ABIT_UGURU_NAME,
        },
-       .probe  = abituguru_probe,
-       .remove = __devexit_p(abituguru_remove),
+       .probe          = abituguru_probe,
+       .remove         = __devexit_p(abituguru_remove),
+       .suspend        = abituguru_suspend,
+       .resume         = abituguru_resume,
 };
 
 static int __init abituguru_detect(void)
@@ -1374,6 +1448,15 @@ static int __init abituguru_init(void)
        int address, err;
        struct resource res = { .flags = IORESOURCE_IO };
 
+#ifdef CONFIG_DMI
+       const char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+
+       /* safety check, refuse to load on non Abit motherboards */
+       if (!force && (!board_vendor ||
+                       strcmp(board_vendor, "http://www.abit.com.tw/")))
+               return -ENODEV;
+#endif
+
        address = abituguru_detect();
        if (address < 0)
                return address;