From 91afa07664a8d26f51fb59b13fd5fa3592b728bc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Apr 2018 12:01:58 +0200 Subject: ACPI / battery: Remove initializer for unused ident dmi_system_id The battery code does not use the dmi_system_id ident member, so there is no need to initialize it. This saves us storing the unused strings as as const data. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/battery.c') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index bdb24d636d9a..338432cbef09 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1334,16 +1334,16 @@ battery_notification_delay_quirk(const struct dmi_system_id *d) static const struct dmi_system_id bat_dmi_table[] __initconst = { { + /* NEC LZ750/LS */ .callback = battery_bix_broken_package_quirk, - .ident = "NEC LZ750/LS", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "NEC"), DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"), }, }, { + /* Acer Aspire V5-573G */ .callback = battery_notification_delay_quirk, - .ident = "Acer Aspire V5-573G", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"), -- cgit From 19fffc8450d4378580a8f019b195c4617083176f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Apr 2018 12:01:59 +0200 Subject: ACPI / battery: Add handling for devices which wrongly report discharging state On quite a few devices the battery code in the ACPI tables is buggy and first checks the charging status bits of the charger-IC, and if those report not charging it will report discharging, without looking at the presence of AC power or at the battery dis(charge) current from the fuel-gauge. This causes the wrong status to be reported for the battery in the following quite common scenario: 1) Plug in charger while battery is say half full, battery starts charging, charging state bits indicate: pre-charge or fast-charge, ACPI reported battery status is ok 2) When fully charged charging state bits indicate: end-of-charge, ACPI reported battery status is ok 3) unplug the charger, wait 1 minute, replug. Now the battery voltage is still above the start-charging threshold, so the charger will not start charging to avoid wrecking the battery by repeatedly recharging the last 1% capacity. The charger IC charging state bits now are all 0 (not-charging) and the broken ACPI code wrongly translate this to "discharging" and ends up setting the ACPI_BATTERY_STATE_DISCHARGING bit in its state field. Reporting this "not charging" state as discharging is confusing for users, making the user think his adapter/power-brick is broken or not properly plugged in. This commit adds a helper for handling the ACPI_BATTERY_STATE_DISCHARGING state. This helper checks if we're an AC and the current going out of the battery is 0 and in that case reports a status of "not charging" to userspace rather then "discharging". This replaces commit c68f0676ef7d ("ACPI / battery: Add quirk for Asus GL502VSK and UX305LA"), a previous fix for this which was reverted. Signed-off-by: Hans de Goede Reviewed-by: Daniel Drake Reviewed-by: Sebastian Reichel Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/acpi/battery.c') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 338432cbef09..bd36cb5c3fe1 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -215,6 +215,19 @@ static bool acpi_battery_is_degraded(struct acpi_battery *battery) battery->full_charge_capacity < battery->design_capacity; } +static int acpi_battery_handle_discharging(struct acpi_battery *battery) +{ + /* + * Some devices wrongly report discharging if the battery's charge level + * was above the device's start charging threshold atm the AC adapter + * was plugged in and the device thus did not start a new charge cycle. + */ + if (power_supply_is_system_supplied() && battery->rate_now == 0) + return POWER_SUPPLY_STATUS_NOT_CHARGING; + + return POWER_SUPPLY_STATUS_DISCHARGING; +} + static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -230,7 +243,7 @@ static int acpi_battery_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_STATUS: if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + val->intval = acpi_battery_handle_discharging(battery); else if (battery->state & ACPI_BATTERY_STATE_CHARGING) val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (acpi_battery_is_charged(battery)) -- cgit From 1b799c5cf031c2b615f4b21150eafde3ff227788 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Apr 2018 12:02:00 +0200 Subject: ACPI / battery: Ignore AC state in handle_discharging on systems where it is broken On some devices the "AC" interface ACPI AML code uses the exact same broken logic which is causing the battery code to wrongly report discharging to determine the "AC" state. Specifically the ACPI AML code is checking the charging status bits of the charger-IC rather then the vbus present or power-good status bits. This makes our workaround for devices which wrongly report discharging when plugged into AC while the charge is above the start charging threshold not work on these devices. This commit adds a battery_ac_is_broken flag and when that is set it skips the power_supply_is_system_supplied() check in the workaround fixing this. This flag gets set by a DMI quirk selected by systems where we know the AC AML code is broken in this way *and* the rate_now value can be trusted. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/acpi/battery.c') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index bd36cb5c3fe1..c63b6a14ad95 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -74,6 +74,7 @@ static async_cookie_t async_cookie; static bool battery_driver_registered; static int battery_bix_broken_package; static int battery_notification_delay_ms; +static int battery_ac_is_broken; static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); @@ -222,7 +223,8 @@ static int acpi_battery_handle_discharging(struct acpi_battery *battery) * was above the device's start charging threshold atm the AC adapter * was plugged in and the device thus did not start a new charge cycle. */ - if (power_supply_is_system_supplied() && battery->rate_now == 0) + if ((battery_ac_is_broken || power_supply_is_system_supplied()) && + battery->rate_now == 0) return POWER_SUPPLY_STATUS_NOT_CHARGING; return POWER_SUPPLY_STATUS_DISCHARGING; @@ -1345,6 +1347,13 @@ battery_notification_delay_quirk(const struct dmi_system_id *d) return 0; } +static int __init +battery_ac_is_broken_quirk(const struct dmi_system_id *d) +{ + battery_ac_is_broken = 1; + return 0; +} + static const struct dmi_system_id bat_dmi_table[] __initconst = { { /* NEC LZ750/LS */ @@ -1362,6 +1371,17 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"), }, }, + { + /* Point of View mobii wintab p800w */ + .callback = battery_ac_is_broken_quirk, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), + /* Above matches are too generic, add bios-date match */ + DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), + }, + }, {}, }; -- cgit From ec625a37c10c64681c00459912ce7318e133bf7a Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Wed, 18 Apr 2018 14:04:39 +0200 Subject: ACPI / battery: Add quirk to avoid checking for PMIC with native driver With commit dccfae6d4f4c (ACPI / battery: Add a blacklist with PMIC ACPI HIDs with a native battery driver) a blacklist was introduced to avoid using the ACPI drivers for the battery when a native PMIC driver was already present. While this is in general a good idea (because of broken DSDT or proprietary and undocumented ACPI opregions for the ACPI battery devices) there are some Cherry Trail devices which use a separate FG controller despite the AXP288 having a builtin FG. The net effect of blacklisting the ACPI drivers is that on these devices the battery reporting is broken since the AXP288 PMIC FG bits are not actually used on this hardware. This commit adds a battery_do_not_check_pmic quirk for this and sets this on the 2 devices currently known to use a separate FG controller, the ECS EF20EA and the Lenovo Ideapad Miix 320. [hdegoede@redhat.com: Merge the quirk handling and the adding of the DMI table entry into 1 commit, add a second DMI entry for the Miix 320.] Signed-off-by: Carlo Caione Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'drivers/acpi/battery.c') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c63b6a14ad95..572845fafb00 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -75,6 +75,7 @@ static bool battery_driver_registered; static int battery_bix_broken_package; static int battery_notification_delay_ms; static int battery_ac_is_broken; +static int battery_check_pmic = 1; static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); @@ -1354,6 +1355,13 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d) return 0; } +static int __init +battery_do_not_check_pmic_quirk(const struct dmi_system_id *d) +{ + battery_check_pmic = 0; + return 0; +} + static const struct dmi_system_id bat_dmi_table[] __initconst = { { /* NEC LZ750/LS */ @@ -1382,6 +1390,22 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), }, }, + { + /* ECS EF20EA */ + .callback = battery_do_not_check_pmic_quirk, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), + }, + }, + { + /* Lenovo Ideapad Miix 320 */ + .callback = battery_do_not_check_pmic_quirk, + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), + }, + }, {}, }; @@ -1521,16 +1545,18 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) unsigned int i; int result; - for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++) - if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) { - pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME - ": found native %s PMIC, not loading\n", - acpi_battery_blacklist[i]); - return; - } - dmi_check_system(bat_dmi_table); + if (battery_check_pmic) { + for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++) + if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) { + pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME + ": found native %s PMIC, not loading\n", + acpi_battery_blacklist[i]); + return; + } + } + #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) -- cgit