hwmon: (adt7475) Fix sysfs file names
[safe/jmp/linux-2.6] / drivers / acpi / sbshc.c
index 12a1532..d933980 100644 (file)
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-#include <acpi/actypes.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include "sbshc.h"
 
+#define PREFIX "ACPI: "
+
 #define ACPI_SMB_HC_CLASS      "smbus_host_controller"
 #define ACPI_SMB_HC_DEVICE_NAME        "ACPI SMBus HC"
 
@@ -107,16 +108,28 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
        if (wait_event_timeout(hc->wait, smb_check_done(hc),
                               msecs_to_jiffies(timeout)))
                return 0;
+       /*
+        * After the timeout happens, OS will try to check the status of SMbus.
+        * If the status is what OS expected, it will be regarded as the bogus
+        * timeout.
+        */
+       if (smb_check_done(hc))
+               return 0;
        else
                return -ETIME;
 }
 
-int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address,
-                   u8 command, u8 *data, u8 length)
+static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
+                                 u8 address, u8 command, u8 *data, u8 length)
 {
        int ret = -EFAULT, i;
        u8 temp, sz = 0;
 
+       if (!hc) {
+               printk(KERN_ERR PREFIX "host controller is not configured\n");
+               return ret;
+       }
+
        mutex_lock(&hc->lock);
        if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
                goto end;
@@ -125,7 +138,6 @@ int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address,
                goto end;
        }
        smb_hc_write(hc, ACPI_SMB_COMMAND, command);
-       smb_hc_write(hc, ACPI_SMB_COMMAND, command);
        if (!(protocol & 0x01)) {
                smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length);
                for (i = 0; i < length; ++i)
@@ -202,10 +214,9 @@ int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc)
 
 EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback);
 
-static void acpi_smbus_callback(void *context)
+static inline void acpi_smbus_callback(void *context)
 {
        struct acpi_smb_hc *hc = context;
-
        if (hc->callback)
                hc->callback(hc->context);
 }
@@ -214,6 +225,7 @@ static int smbus_alarm(void *context)
 {
        struct acpi_smb_hc *hc = context;
        union acpi_smb_status status;
+       u8 address;
        if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
                return 0;
        /* Check if it is only a completion notify */
@@ -222,10 +234,18 @@ static int smbus_alarm(void *context)
        if (!status.fields.alarm)
                return 0;
        mutex_lock(&hc->lock);
+       smb_hc_read(hc, ACPI_SMB_ALARM_ADDRESS, &address);
        status.fields.alarm = 0;
        smb_hc_write(hc, ACPI_SMB_STATUS, status.raw);
-       if (hc->callback)
-               acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc);
+       /* We are only interested in events coming from known devices */
+       switch (address >> 1) {
+               case ACPI_SBS_CHARGER:
+               case ACPI_SBS_MANAGER:
+               case ACPI_SBS_BATTERY:
+                       acpi_os_execute(OSL_GPE_HANDLER,
+                                       acpi_smbus_callback, hc);
+               default:;
+       }
        mutex_unlock(&hc->lock);
        return 0;
 }
@@ -239,7 +259,7 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
 static int acpi_smbus_hc_add(struct acpi_device *device)
 {
        int status;
-       unsigned long val;
+       unsigned long long val;
        struct acpi_smb_hc *hc;
 
        if (!device)
@@ -263,7 +283,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
        hc->ec = acpi_driver_data(device->parent);
        hc->offset = (val >> 8) & 0xff;
        hc->query_bit = val & 0xff;
-       acpi_driver_data(device) = hc;
+       device->driver_data = hc;
 
        acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
        printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
@@ -284,6 +304,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
        hc = acpi_driver_data(device);
        acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
        kfree(hc);
+       device->driver_data = NULL;
        return 0;
 }