From patchwork Sat Jan 9 23:07:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pavel Machek X-Patchwork-Id: 7993821 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 235869F1CC for ; Sat, 9 Jan 2016 23:07:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CC598202B8 for ; Sat, 9 Jan 2016 23:07:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AA64520272 for ; Sat, 9 Jan 2016 23:07:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756643AbcAIXHP (ORCPT ); Sat, 9 Jan 2016 18:07:15 -0500 Received: from atrey.karlin.mff.cuni.cz ([195.113.26.193]:36970 "EHLO atrey.karlin.mff.cuni.cz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756173AbcAIXHN (ORCPT ); Sat, 9 Jan 2016 18:07:13 -0500 Received: by atrey.karlin.mff.cuni.cz (Postfix, from userid 512) id 4517682387; Sun, 10 Jan 2016 00:07:10 +0100 (CET) Date: Sun, 10 Jan 2016 00:07:09 +0100 From: Pavel Machek To: pali.rohar@gmail.com, sre@debian.org, sre@ring0.de, kernel list , linux-arm-kernel , linux-omap@vger.kernel.org, tony@atomide.com, khilman@kernel.org, aaro.koskinen@iki.fi, ivo.g.dimitrov.75@gmail.com, patrikbachan@gmail.com, serge@hallyn.com Cc: a.hajda@samsung.com, afd@ti.com Subject: /sys/class/power_supply/bq27200-0/capacity changed meaning between 4.1 and 4.4? Message-ID: <20160109230709.GA30551@amd> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hi! Did /sys/class/power_supply/bq27200-0/capacity change meaning between 4.1 and 4.4? It used to report battery capacity remaining in percent. Not sure what it reports now, but ain't in percent.... pavel@n900:/my/tui/ofone$ cat /sys/class/power_supply/bq27200-0/capacity 7497 pavel@n900:/my/tui/ofone$ uname -a Linux n900 4.4.0-rc8-omap3-149467-g69aafd8-dirty #114 PREEMPT Sat Jan 9 21:44:00 CET 2016 armv7l GNU/Linux pavel@n900:/my/tui/ofone$ And power_supply_class.txt says: ~ ~ ~ ~ ~ ~ ~ Charge/Energy/Capacity - how to not confuse ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity" ~ ~ of battery, this class distinguish these terms. Don't mix them! ~ ~ ~ ~ CHARGE_* attributes represents capacity in µAh only. ~ ~ ENERGY_* attributes represents capacity in µWh only. ~ ~ CAPACITY attribute represents capacity in *percents*, from 0 to 100. ~ --- hmm. So that seems to be a mistake. pavel@n900:/my/tui/ofone$ cat /sys/class/power_supply/bq27200-0/capacity 7497 pavel@n900:/my/tui/ofone$ cat /sys/class/power_supply/bq27200-0/capacity 16713 pavel@n900:/my/tui/ofone$ cat /sys/class/power_supply/bq27200-0/capacity 25162 Converting them to hex gives rather strange values. Hmm. .... what is this? Git blames Andrew F. Davis. The first part of code suggests whole cache needs to be initialized... but the second part of the code only initializes cache.time_to_empty (for example) conditionaly. Are you sure? if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) { dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); cache.capacity = -ENODATA; cache.energy = -ENODATA; cache.time_to_empty = -ENODATA; cache.time_to_empty_avg = -ENODATA; cache.time_to_full = -ENODATA; cache.charge_full = -ENODATA; cache.health = -ENODATA; } else { if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TT\ ECP); if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); cache.charge_full = bq27xxx_battery_read_fcc(di); cache.capacity = bq27xxx_battery_read_soc(di); if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) cache.energy = bq27xxx_battery_read_energy(di); cache.health = bq27xxx_battery_read_health(di); } But that does not explain the wrong capacity.. -static inline int bq27xxx_read(struct bq27xxx_device_info *di, u8 reg, +static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, bool single) { This is pretty anti-social function now has completely different meaning, yet same name and compatible enough not to catch mistakes. And sure enough: static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di,u8 reg) { int charge; charge = bq27xxx_read(di, reg, false); The internal functions already check for non-existent registers. We can kill the debug prints and reuse that... its better than not initializing half the struct. The types should in bq27xxx_battery_read_time should be certainly fixed like the patch below suggests. The patch does not compile, but I should be sleeping, not trying to understand crazy code. Whoever wrote it, please fix it. Maybe you can just do cache.capacity = -ENODATA; cache.energy = -ENODATA; cache.time_to_empty = -ENODATA; cache.time_to_empty_avg = -ENODATA; cache.time_to_full = -ENODATA; cache.charge_full = -ENODATA; cache.health = -ENODATA; undonditionaly so that half of file does not need updating. Pavel diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c index 880233c..e9f26f5 100644 --- a/drivers/power/bq27xxx_battery.c +++ b/drivers/power/bq27xxx_battery.c @@ -483,11 +483,11 @@ static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di) * Return a battery charge value in µAh * Or < 0 if something fails. */ -static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg) +static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, int reg_index) { int charge; - charge = bq27xxx_read(di, reg, false); + charge = bq27xxx_read(di, reg_index, false); if (charge < 0) { dev_dbg(di->dev, "error reading charge register %02x: %d\n", reg, charge); @@ -561,7 +561,6 @@ static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di) ae = bq27xxx_read(di, BQ27XXX_REG_AE, false); if (ae < 0) { - dev_dbg(di->dev, "error reading available energy\n"); return ae; } @@ -602,8 +601,6 @@ static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di) int cyct; cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false); - if (cyct < 0) - dev_err(di->dev, "error reading cycle count total\n"); return cyct; } @@ -612,14 +609,12 @@ static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di) * Read a time register. * Return < 0 if something fails. */ -static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg) +static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, int reg_index) { int tval; - tval = bq27xxx_read(di, reg, false); + tval = bq27xxx_read(di, reg_index, false); if (tval < 0) { - dev_dbg(di->dev, "error reading time register %02x: %d\n", - reg, tval); return tval; } @@ -639,8 +634,6 @@ static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di) tval = bq27xxx_read(di, BQ27XXX_REG_AP, false); if (tval < 0) { - dev_err(di->dev, "error reading average power register %02x: %d\n", - BQ27XXX_REG_AP, tval); return tval; } @@ -731,22 +724,16 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di) cache.charge_full = -ENODATA; cache.health = -ENODATA; } else { - if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) - cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); - if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) - cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); - if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) - cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); + cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); + cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); + cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); cache.charge_full = bq27xxx_battery_read_fcc(di); cache.capacity = bq27xxx_battery_read_soc(di); - if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) - cache.energy = bq27xxx_battery_read_energy(di); + cache.energy = bq27xxx_battery_read_energy(di); cache.health = bq27xxx_battery_read_health(di); } - if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) - cache.cycle_count = bq27xxx_battery_read_cyct(di); - if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR) - cache.power_avg = bq27xxx_battery_read_pwr_avg(di); + cache.cycle_count = bq27xxx_battery_read_cyct(di); + cache.power_avg = bq27xxx_battery_read_pwr_avg(di); /* We only have to read charge design full once */ if (di->charge_design_full <= 0)