All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tony Lindgren <tony@atomide.com>
To: Liam Breck <liam@networkimprov.net>
Cc: Sebastian Reichel <sre@kernel.org>,
	Liam Breck <kernel@networkimprov.net>,
	"Mark A . Greer" <mgreer@animalcreek.com>,
	linux-pm@vger.kernel.org, linux-omap@vger.kernel.org
Subject: Re: [PATCH 2/2] power: bq24190_charger: Use PM runtime autosuspend
Date: Mon, 23 Jan 2017 17:27:02 -0800	[thread overview]
Message-ID: <20170124012702.GA7403@atomide.com> (raw)
In-Reply-To: <CAKvHMgQKPZcdBPMUH-3_e-M4sHPijEH59019bygmi+o2y4B+Rw@mail.gmail.com>

* Liam Breck <liam@networkimprov.net> [170120 16:48]:
> On Fri, Jan 20, 2017 at 2:04 PM, Tony Lindgren <tony@atomide.com> wrote:
> > We can get quite a few interrupts when the battery is trickle charging.
> > Let's enable PM runtime autosuspend to avoid constantly toggling device
> > state.
> 
> Which device state would constantly toggle?

The device driver PM runtime state. I've updated the description for that.

> > Cc: Matt Ranostay <matt@ranostay.consulting>
> 
> We can probably drop Matt from this thread; he's been busy with the
> fuel gauge, etc.

Fair enough :)

> > @@ -427,11 +428,20 @@ static ssize_t bq24190_sysfs_show(struct device *dev,
> >         if (!info)
> >                 return -EINVAL;
> >
> > +       ret = pm_runtime_get_sync(bdi->dev);
> > +       if (ret < 0)
> > +               return ret;
> > +
> >         ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
> >         if (ret)
> > -               return ret;
> > +               count = ret;
> > +       else
> > +               count = scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
> 
> Unless it violates a style guide, I prefer
>   count = ret ? ret : scnprintf(buf, PAGE_SIZE, "%hhx\n", v);

I don't like that, I find it hard to read.

> > @@ -1249,7 +1286,9 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
> >         u8 v;
> >         int ret;
> >
> > -       pm_runtime_get_sync(bdi->dev);
> > +       ret = pm_runtime_get_sync(bdi->dev);
> > +       if (ret < 0)
> > +               return ret;
> 
> Why is pm_runtime_*() necessary in this function?
> probe() already calls pm_runtime_*() around hw_init(); nothing else calls it.

Good point, it's not needed. I've removed the pm_runtime_calls.

> > @@ -1364,12 +1405,16 @@ static int bq24190_probe(struct i2c_client *client,
> >         }
> 
> v1 patchset called enable_irq_wake() here.
> v2 change list does not mention its removal.

Oops sorry about that, that's a mismerge on the rebase. I've added that
now to after request_threaded_irq().

> > -out4:
> > +out5:
> >         bq24190_sysfs_remove_group(bdi);
> >
> > -out3:
> > +out4:
> >         power_supply_unregister(bdi->battery);
> >
> > -out2:
> > +out3:
> >         power_supply_unregister(bdi->charger);
> >
> > +out2:
> > +       pm_runtime_put_sync(dev);
> > +
> 
> v2 change list does not mention this addition

Well I mentioned the changes for "mostly for the probe error handling"
in the cover letter and that's needed as we now have the multiple out
labels.

> > @@ -1430,9 +1482,13 @@ static int bq24190_probe(struct i2c_client *client,
> >  static int bq24190_remove(struct i2c_client *client)
> >  {
> >         struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
> > +       int ret;
> >
> > -       pm_runtime_get_sync(bdi->dev);
> > +       ret = pm_runtime_get_sync(bdi->dev);
> > +       if (ret < 0)
> > +               dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
> >         bq24190_register_reset(bdi);
> > +       pm_runtime_dont_use_autosuspend(bdi->dev);
> >         pm_runtime_put_sync(bdi->dev);
> 
> Should skip these if get_sync() failed?

Yes, I've fixed it.

> Is pm_runtime_disable() needed here?

Yes it's best to keep the pm_runtime calls always paired.

> > @@ -1480,10 +1536,14 @@ static int bq24190_pm_suspend(struct device *dev)
> >  {
> >         struct i2c_client *client = to_i2c_client(dev);
> >         struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
> > +       int error;
> >
> > -       pm_runtime_get_sync(bdi->dev);
> > +       error = pm_runtime_get_sync(bdi->dev);
> > +       if (error < 0)
> > +               dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
> >         bq24190_register_reset(bdi);
> > -       pm_runtime_put_sync(bdi->dev);
> > +       pm_runtime_mark_last_busy(bdi->dev);
> > +       pm_runtime_put_autosuspend(bdi->dev);
> 
> Should skip these if get_sync() failed?

Yes fixed.

> > @@ -1492,15 +1552,19 @@ static int bq24190_pm_resume(struct device *dev)
> >  {
> >         struct i2c_client *client = to_i2c_client(dev);
> >         struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
> > +       int error;
> >
> >         bdi->f_reg = 0;
> >         bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
> >
> > -       pm_runtime_get_sync(bdi->dev);
> > +       error = pm_runtime_get_sync(bdi->dev);
> > +       if (error < 0)
> > +               dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
> >         bq24190_register_reset(bdi);
> >         bq24190_set_mode_host(bdi);
> >         bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
> > -       pm_runtime_put_sync(bdi->dev);
> > +       pm_runtime_mark_last_busy(bdi->dev);
> > +       pm_runtime_put_autosuspend(bdi->dev);
> 
> Should skip these if get_sync() failed?

Here too.

Updated patch below with fixes for the comments above. I've dropped Mark's
ack as there are several changes so please re-review.

Regards,

Tony

8< ---------------------------
>From tony Mon Sep 17 00:00:00 2001
From: Tony Lindgren <tony@atomide.com>
Date: Fri, 20 Jan 2017 09:58:51 -0800
Subject: [PATCH] power: bq24190_charger: Use PM runtime autosuspend

We can get quite a few interrupts when the battery is trickle charging.
Let's enable PM runtime autosuspend to avoid constantly toggling device
driver PM runtime state.

Let's use a 600 ms timeout as that's how long the USB chager detection
might take.

Cc: Liam Breck <kernel@networkimprov.net>
Cc: Mark Greer <mgreer@animalcreek.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/power/supply/bq24190_charger.c | 147 ++++++++++++++++++++++-----------
 1 file changed, 101 insertions(+), 46 deletions(-)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -420,6 +420,7 @@ static ssize_t bq24190_sysfs_show(struct device *dev,
 	struct power_supply *psy = dev_get_drvdata(dev);
 	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
 	struct bq24190_sysfs_field_info *info;
+	ssize_t count;
 	int ret;
 	u8 v;
 
@@ -427,11 +428,20 @@ static ssize_t bq24190_sysfs_show(struct device *dev,
 	if (!info)
 		return -EINVAL;
 
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
+
 	ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
 	if (ret)
-		return ret;
+		count = ret;
+	else
+		count = scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
 
-	return scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
+
+	return count;
 }
 
 static ssize_t bq24190_sysfs_store(struct device *dev,
@@ -451,9 +461,16 @@ static ssize_t bq24190_sysfs_store(struct device *dev,
 	if (ret < 0)
 		return ret;
 
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
+
 	ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
 	if (ret)
-		return ret;
+		count = ret;
+
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
 
 	return count;
 }
@@ -795,7 +812,9 @@ static int bq24190_charger_get_property(struct power_supply *psy,
 
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
-	pm_runtime_get_sync(bdi->dev);
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
@@ -835,7 +854,9 @@ static int bq24190_charger_get_property(struct power_supply *psy,
 		ret = -ENODATA;
 	}
 
-	pm_runtime_put_sync(bdi->dev);
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
+
 	return ret;
 }
 
@@ -848,7 +869,9 @@ static int bq24190_charger_set_property(struct power_supply *psy,
 
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
-	pm_runtime_get_sync(bdi->dev);
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
@@ -864,7 +887,9 @@ static int bq24190_charger_set_property(struct power_supply *psy,
 		ret = -EINVAL;
 	}
 
-	pm_runtime_put_sync(bdi->dev);
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
+
 	return ret;
 }
 
@@ -1065,7 +1090,9 @@ static int bq24190_battery_get_property(struct power_supply *psy,
 
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
-	pm_runtime_get_sync(bdi->dev);
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:
@@ -1093,7 +1120,9 @@ static int bq24190_battery_get_property(struct power_supply *psy,
 		ret = -ENODATA;
 	}
 
-	pm_runtime_put_sync(bdi->dev);
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
+
 	return ret;
 }
 
@@ -1106,7 +1135,9 @@ static int bq24190_battery_set_property(struct power_supply *psy,
 
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
-	pm_runtime_get_sync(bdi->dev);
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ONLINE:
@@ -1119,7 +1150,9 @@ static int bq24190_battery_set_property(struct power_supply *psy,
 		ret = -EINVAL;
 	}
 
-	pm_runtime_put_sync(bdi->dev);
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
+
 	return ret;
 }
 
@@ -1234,11 +1267,15 @@ static void bq24190_check_status(struct bq24190_dev_info *bdi)
 static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
 {
 	struct bq24190_dev_info *bdi = data;
+	int ret;
 
 	bdi->irq_event = true;
-	pm_runtime_get_sync(bdi->dev);
+	ret = pm_runtime_get_sync(bdi->dev);
+	if (ret < 0)
+		return ret;
 	bq24190_check_status(bdi);
-	pm_runtime_put_sync(bdi->dev);
+	pm_runtime_mark_last_busy(bdi->dev);
+	pm_runtime_put_autosuspend(bdi->dev);
 	bdi->irq_event = false;
 
 	return IRQ_HANDLED;
@@ -1249,33 +1286,26 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
 	u8 v;
 	int ret;
 
-	pm_runtime_get_sync(bdi->dev);
-
 	/* First check that the device really is what its supposed to be */
 	ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,
 			BQ24190_REG_VPRS_PN_MASK,
 			BQ24190_REG_VPRS_PN_SHIFT,
 			&v);
 	if (ret < 0)
-		goto out;
+		return ret;
 
-	if (v != bdi->model) {
-		ret = -ENODEV;
-		goto out;
-	}
+	if (v != bdi->model)
+		return -ENODEV;
 
 	ret = bq24190_register_reset(bdi);
 	if (ret < 0)
-		goto out;
+		return ret;
 
 	ret = bq24190_set_mode_host(bdi);
 	if (ret < 0)
-		goto out;
+		return ret;
 
-	ret = bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
-out:
-	pm_runtime_put_sync(bdi->dev);
-	return ret;
+	return bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
 }
 
 #ifdef CONFIG_OF
@@ -1364,12 +1394,16 @@ static int bq24190_probe(struct i2c_client *client,
 	}
 
 	pm_runtime_enable(dev);
-	pm_runtime_resume(dev);
+	pm_runtime_set_autosuspend_delay(dev, 600);
+	pm_runtime_use_autosuspend(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0)
+		goto out1;
 
 	ret = bq24190_hw_init(bdi);
 	if (ret < 0) {
 		dev_err(dev, "Hardware init failed\n");
-		goto out1;
+		goto out2;
 	}
 
 	charger_cfg.drv_data = bdi;
@@ -1380,7 +1414,7 @@ static int bq24190_probe(struct i2c_client *client,
 	if (IS_ERR(bdi->charger)) {
 		dev_err(dev, "Can't register charger\n");
 		ret = PTR_ERR(bdi->charger);
-		goto out1;
+		goto out2;
 	}
 
 	battery_cfg.drv_data = bdi;
@@ -1389,13 +1423,13 @@ static int bq24190_probe(struct i2c_client *client,
 	if (IS_ERR(bdi->battery)) {
 		dev_err(dev, "Can't register battery\n");
 		ret = PTR_ERR(bdi->battery);
-		goto out2;
+		goto out3;
 	}
 
 	ret = bq24190_sysfs_create_group(bdi);
 	if (ret) {
 		dev_err(dev, "Can't create sysfs entries\n");
-		goto out3;
+		goto out4;
 	}
 
 	bdi->initialized = true;
@@ -1406,21 +1440,30 @@ static int bq24190_probe(struct i2c_client *client,
 			"bq24190-charger", bdi);
 	if (ret < 0) {
 		dev_err(dev, "Can't set up irq handler\n");
-		goto out4;
+		goto out5;
 	}
 
+	enable_irq_wake(bdi->irq);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
 	return 0;
 
-out4:
+out5:
 	bq24190_sysfs_remove_group(bdi);
 
-out3:
+out4:
 	power_supply_unregister(bdi->battery);
 
-out2:
+out3:
 	power_supply_unregister(bdi->charger);
 
+out2:
+	pm_runtime_put_sync(dev);
+
 out1:
+	pm_runtime_dont_use_autosuspend(dev);
 	pm_runtime_disable(dev);
 	if (bdi->gpio_int)
 		gpio_free(bdi->gpio_int);
@@ -1431,13 +1474,17 @@ static int bq24190_remove(struct i2c_client *client)
 {
 	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
 
-	pm_runtime_get_sync(bdi->dev);
-	bq24190_register_reset(bdi);
-	pm_runtime_put_sync(bdi->dev);
+	if (!pm_runtime_get_sync(bdi->dev)) {
+		bq24190_register_reset(bdi);
+		pm_runtime_put_sync(bdi->dev);
+	} else {
+		dev_warn(bdi->dev, "pm_runtime_get failed\n");
+	}
 
 	bq24190_sysfs_remove_group(bdi);
 	power_supply_unregister(bdi->battery);
 	power_supply_unregister(bdi->charger);
+	pm_runtime_dont_use_autosuspend(bdi->dev);
 	pm_runtime_disable(bdi->dev);
 
 	if (bdi->gpio_int)
@@ -1481,9 +1528,13 @@ static int bq24190_pm_suspend(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
 
-	pm_runtime_get_sync(bdi->dev);
-	bq24190_register_reset(bdi);
-	pm_runtime_put_sync(bdi->dev);
+	if (!pm_runtime_get_sync(bdi->dev)) {
+		bq24190_register_reset(bdi);
+		pm_runtime_mark_last_busy(bdi->dev);
+		pm_runtime_put_autosuspend(bdi->dev);
+	} else {
+		dev_warn(bdi->dev, "pm_runtime_get failed\n");
+	}
 
 	return 0;
 }
@@ -1496,11 +1547,15 @@ static int bq24190_pm_resume(struct device *dev)
 	bdi->f_reg = 0;
 	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
 
-	pm_runtime_get_sync(bdi->dev);
-	bq24190_register_reset(bdi);
-	bq24190_set_mode_host(bdi);
-	bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
-	pm_runtime_put_sync(bdi->dev);
+	if (!pm_runtime_get_sync(bdi->dev)) {
+		bq24190_register_reset(bdi);
+		bq24190_set_mode_host(bdi);
+		bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
+		pm_runtime_mark_last_busy(bdi->dev);
+		pm_runtime_put_autosuspend(bdi->dev);
+	} else {
+		dev_warn(bdi->dev, "pm_runtime_get failed\n");
+	}
 
 	/* Things may have changed while suspended so alert upper layer */
 	power_supply_changed(bdi->charger);
-- 
2.11.0

  reply	other threads:[~2017-01-24  1:27 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-20 22:04 [PATCH 0/2] Two bq24190 PM improvments Tony Lindgren
2017-01-20 22:04 ` [PATCH 1/2] power: bq24190_charger: Check the interrupt status on resume Tony Lindgren
2017-01-21  8:08   ` Liam Breck
2017-01-22  1:51     ` Sebastian Reichel
2017-01-22  1:54   ` Sebastian Reichel
2017-01-24  0:47     ` Tony Lindgren
2017-01-20 22:04 ` [PATCH 2/2] power: bq24190_charger: Use PM runtime autosuspend Tony Lindgren
2017-01-21  0:47   ` Liam Breck
2017-01-24  1:27     ` Tony Lindgren [this message]
2017-01-24  3:34       ` Liam Breck
2017-01-24 18:29         ` Tony Lindgren
2017-01-24 23:05           ` Mark Greer
2017-01-26 16:20             ` Tony Lindgren
2017-01-26 23:56           ` Liam Breck
2017-01-30 23:55             ` Tony Lindgren
2017-01-31  0:01               ` Liam Breck
2017-01-31  0:04                 ` Tony Lindgren
  -- strict thread matches above, loose matches on Subject: below --
2017-01-31  0:02 [PATCHv2 0/2] Two bq24190 PM improvments Tony Lindgren
2017-01-31  0:02 ` [PATCH 2/2] power: bq24190_charger: Use PM runtime autosuspend Tony Lindgren
2017-01-31  0:14   ` Liam Breck
2017-01-31  0:36     ` Tony Lindgren
2017-02-03  1:43       ` Liam Breck
2017-02-03  3:44         ` Tony Lindgren
2017-02-03 10:38       ` Liam Breck
2017-02-03 18:54         ` Tony Lindgren
2017-02-03 21:00           ` Liam Breck
2017-02-03 21:17             ` Tony Lindgren
2017-02-03 21:44               ` Liam Breck
2017-02-03 22:28                 ` Tony Lindgren
2017-02-04  0:23               ` Liam Breck
2017-02-07 16:01                 ` Tony Lindgren
2017-02-07 18:20                   ` Liam Breck
2017-02-03 23:09 [PATCHv3 0/2] Two bq24190 PM improvments Tony Lindgren
2017-02-03 23:09 ` [PATCH 2/2] power: bq24190_charger: Use PM runtime autosuspend Tony Lindgren
2017-02-08 21:32   ` Tony Lindgren
2017-02-08 23:12 [PATCHv4 0/2] Two bq24190 PM improvments Tony Lindgren
2017-02-08 23:13 ` [PATCH 2/2] power: bq24190_charger: Use PM runtime autosuspend Tony Lindgren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170124012702.GA7403@atomide.com \
    --to=tony@atomide.com \
    --cc=kernel@networkimprov.net \
    --cc=liam@networkimprov.net \
    --cc=linux-omap@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=mgreer@animalcreek.com \
    --cc=sre@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.