Merge remote-tracking branch 'lsk/v3.10/topic/gator' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / acpi / battery.c
index 99427d7307aff496775cfc25ba373accdcff5699..7ae5ebd1e70ec541f0218f8983148506d768663e 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <linux/delay.h>
 #include <asm/unaligned.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
@@ -1081,6 +1082,28 @@ static struct dmi_system_id bat_dmi_table[] = {
        {},
 };
 
+/*
+ * Some machines'(E,G Lenovo Z480) ECs are not stable
+ * during boot up and this causes battery driver fails to be
+ * probed due to failure of getting battery information
+ * from EC sometimes. After several retries, the operation
+ * may work. So add retry code here and 20ms sleep between
+ * every retries.
+ */
+static int acpi_battery_update_retry(struct acpi_battery *battery)
+{
+       int retry, ret;
+
+       for (retry = 5; retry; retry--) {
+               ret = acpi_battery_update(battery);
+               if (!ret)
+                       break;
+
+               msleep(20);
+       }
+       return ret;
+}
+
 static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
@@ -1100,9 +1123,11 @@ static int acpi_battery_add(struct acpi_device *device)
        if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
                        "_BIX", &handle)))
                set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
-       result = acpi_battery_update(battery);
+
+       result = acpi_battery_update_retry(battery);
        if (result)
                goto fail;
+
 #ifdef CONFIG_ACPI_PROCFS_POWER
        result = acpi_battery_add_fs(device);
 #endif