#include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <asm/unaligned.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
        ACPI_BATTERY_ALARM_PRESENT,
        ACPI_BATTERY_XINFO_PRESENT,
        ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
+       /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
+          switches between mWh and mAh depending on whether the system
+          is running on battery or not.  When mAh is the unit, most
+          reported values are incorrect and need to be adjusted by
+          10000/design_voltage.  Verified on x201, t410, t410s, and x220.
+          Pre-2010 and 2012 models appear to always report in mWh and
+          are thus unaffected (tested with t42, t61, t500, x200, x300,
+          and x230).  Also, in mid-2012 Lenovo issued a BIOS update for
+          the 2011 models that fixes the issue (tested on x220 with a
+          post-1.29 BIOS), but as of Nov. 2012, no such update is
+          available for the 2010 models.  */
+       ACPI_BATTERY_QUIRK_THINKPAD_MAH,
 };
 
 struct acpi_battery {
        kfree(buffer.pointer);
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
                battery->full_charge_capacity = battery->design_capacity;
+       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+           battery->power_unit && battery->design_voltage) {
+               battery->design_capacity = battery->design_capacity *
+                   10000 / battery->design_voltage;
+               battery->full_charge_capacity = battery->full_charge_capacity *
+                   10000 / battery->design_voltage;
+               battery->design_capacity_warning =
+                   battery->design_capacity_warning *
+                   10000 / battery->design_voltage;
+               /* Curiously, design_capacity_low, unlike the rest of them,
+                  is correct.  */
+               /* capacity_granularity_* equal 1 on the systems tested, so
+                  it's impossible to tell if they would need an adjustment
+                  or not if their values were higher.  */
+       }
        return result;
 }
 
            && battery->capacity_now >= 0 && battery->capacity_now <= 100)
                battery->capacity_now = (battery->capacity_now *
                                battery->full_charge_capacity) / 100;
+       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+           battery->power_unit && battery->design_voltage) {
+               battery->capacity_now = battery->capacity_now *
+                   10000 / battery->design_voltage;
+       }
        return result;
 }
 
        mutex_unlock(&battery->sysfs_lock);
 }
 
+static void find_battery(const struct dmi_header *dm, void *private)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)private;
+       /* Note: the hardcoded offsets below have been extracted from
+          the source code of dmidecode.  */
+       if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
+               const u8 *dmi_data = (const u8 *)(dm + 1);
+               int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
+               if (dm->length >= 18)
+                       dmi_capacity *= dmi_data[17];
+               if (battery->design_capacity * battery->design_voltage / 1000
+                   != dmi_capacity &&
+                   battery->design_capacity * 10 == dmi_capacity)
+                       set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+                               &battery->flags);
+       }
+}
+
 /*
  * According to the ACPI spec, some kinds of primary batteries can
  * report percentage battery remaining capacity directly to OS.
                battery->capacity_now = (battery->capacity_now *
                                battery->full_charge_capacity) / 100;
        }
+
+       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
+               return ;
+
+       if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
+               const char *s;
+               s = dmi_get_system_info(DMI_PRODUCT_VERSION);
+               if (s && !strnicmp(s, "ThinkPad", 8)) {
+                       dmi_walk(find_battery, battery);
+                       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+                                    &battery->flags) &&
+                           battery->design_voltage) {
+                               battery->design_capacity =
+                                   battery->design_capacity *
+                                   10000 / battery->design_voltage;
+                               battery->full_charge_capacity =
+                                   battery->full_charge_capacity *
+                                   10000 / battery->design_voltage;
+                               battery->design_capacity_warning =
+                                   battery->design_capacity_warning *
+                                   10000 / battery->design_voltage;
+                               battery->capacity_now = battery->capacity_now *
+                                   10000 / battery->design_voltage;
+                       }
+               }
+       }
 }
 
 static int acpi_battery_update(struct acpi_battery *battery)