linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] regulator: Avoid grabbing regulator lock during suspend/resume
@ 2020-08-04  7:08 Stephen Boyd
  2020-08-05  4:55 ` Doug Anderson
  2020-08-18 16:56 ` Mark Brown
  0 siblings, 2 replies; 3+ messages in thread
From: Stephen Boyd @ 2020-08-04  7:08 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, Liam Girdwood, Matthias Kaehlcke, Douglas Anderson

I see it takes about 5us per regulator to grab the lock, check that this
regulator isn't going to do anything for suspend, and then release the
lock. When that is combined with PMICs that have dozens of regulators we
get into a state where we spend a few miliseconds doing a bunch of
locking operations synchronously to figure out that there's nothing to
do. Let's reorganize the code here a bit so that we don't grab the lock
until we're actually going to do something so that suspend is a little
faster.

Cc: Matthias Kaehlcke <mka@chromium.org>
Cc: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 drivers/regulator/core.c | 75 +++++++++++++++++++++++++++-------------
 1 file changed, 51 insertions(+), 24 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 03154f5b939f..c94b656178ec 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -564,6 +564,30 @@ regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state)
 	}
 }
 
+static const struct regulator_state *
+regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state)
+{
+	const struct regulator_state *rstate;
+
+	rstate = regulator_get_suspend_state(rdev, state);
+	if (rstate == NULL)
+		return NULL;
+
+	/* If we have no suspend mode configuration don't set anything;
+	 * only warn if the driver implements set_suspend_voltage or
+	 * set_suspend_mode callback.
+	 */
+	if (rstate->enabled != ENABLE_IN_SUSPEND &&
+	    rstate->enabled != DISABLE_IN_SUSPEND) {
+		if (rdev->desc->ops->set_suspend_voltage ||
+		    rdev->desc->ops->set_suspend_mode)
+			rdev_warn(rdev, "No configuration\n");
+		return NULL;
+	}
+
+	return rstate;
+}
+
 static ssize_t regulator_uV_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -981,27 +1005,10 @@ static int drms_uA_update(struct regulator_dev *rdev)
 	return err;
 }
 
-static int suspend_set_state(struct regulator_dev *rdev,
-				    suspend_state_t state)
+static int __suspend_set_state(struct regulator_dev *rdev,
+			       const struct regulator_state *rstate)
 {
 	int ret = 0;
-	struct regulator_state *rstate;
-
-	rstate = regulator_get_suspend_state(rdev, state);
-	if (rstate == NULL)
-		return 0;
-
-	/* If we have no suspend mode configuration don't set anything;
-	 * only warn if the driver implements set_suspend_voltage or
-	 * set_suspend_mode callback.
-	 */
-	if (rstate->enabled != ENABLE_IN_SUSPEND &&
-	    rstate->enabled != DISABLE_IN_SUSPEND) {
-		if (rdev->desc->ops->set_suspend_voltage ||
-		    rdev->desc->ops->set_suspend_mode)
-			rdev_warn(rdev, "No configuration\n");
-		return 0;
-	}
 
 	if (rstate->enabled == ENABLE_IN_SUSPEND &&
 		rdev->desc->ops->set_suspend_enable)
@@ -1036,6 +1043,18 @@ static int suspend_set_state(struct regulator_dev *rdev,
 	return ret;
 }
 
+static int suspend_set_initial_state(struct regulator_dev *rdev)
+{
+	const struct regulator_state *rstate;
+
+	rstate = regulator_get_suspend_state_check(rdev,
+			rdev->constraints->initial_state);
+	if (!rstate)
+		return 0;
+
+	return __suspend_set_state(rdev, rstate);
+}
+
 static void print_constraints(struct regulator_dev *rdev)
 {
 	struct regulation_constraints *constraints = rdev->constraints;
@@ -1318,7 +1337,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
 
 	/* do we need to setup our suspend state */
 	if (rdev->constraints->initial_state) {
-		ret = suspend_set_state(rdev, rdev->constraints->initial_state);
+		ret = suspend_set_initial_state(rdev);
 		if (ret < 0) {
 			rdev_err(rdev, "failed to set suspend state\n");
 			return ret;
@@ -5297,9 +5316,14 @@ static int regulator_suspend(struct device *dev)
 	struct regulator_dev *rdev = dev_to_rdev(dev);
 	suspend_state_t state = pm_suspend_target_state;
 	int ret;
+	const struct regulator_state *rstate;
+
+	rstate = regulator_get_suspend_state_check(rdev, state);
+	if (!rstate)
+		return 0;
 
 	regulator_lock(rdev);
-	ret = suspend_set_state(rdev, state);
+	ret = __suspend_set_state(rdev, rstate);
 	regulator_unlock(rdev);
 
 	return ret;
@@ -5316,11 +5340,14 @@ static int regulator_resume(struct device *dev)
 	if (rstate == NULL)
 		return 0;
 
+	/* Avoid grabbing the lock if we don't need to */
+	if (!rdev->desc->ops->resume)
+		return 0;
+
 	regulator_lock(rdev);
 
-	if (rdev->desc->ops->resume &&
-	    (rstate->enabled == ENABLE_IN_SUSPEND ||
-	     rstate->enabled == DISABLE_IN_SUSPEND))
+	if (rstate->enabled == ENABLE_IN_SUSPEND ||
+	    rstate->enabled == DISABLE_IN_SUSPEND)
 		ret = rdev->desc->ops->resume(rdev);
 
 	regulator_unlock(rdev);
-- 
Sent by a computer, using git, on the internet


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] regulator: Avoid grabbing regulator lock during suspend/resume
  2020-08-04  7:08 [PATCH] regulator: Avoid grabbing regulator lock during suspend/resume Stephen Boyd
@ 2020-08-05  4:55 ` Doug Anderson
  2020-08-18 16:56 ` Mark Brown
  1 sibling, 0 replies; 3+ messages in thread
From: Doug Anderson @ 2020-08-05  4:55 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Mark Brown, LKML, Liam Girdwood, Matthias Kaehlcke

Hi,

On Tue, Aug 4, 2020 at 12:08 AM Stephen Boyd <swboyd@chromium.org> wrote:
>
> I see it takes about 5us per regulator to grab the lock, check that this
> regulator isn't going to do anything for suspend, and then release the
> lock. When that is combined with PMICs that have dozens of regulators we
> get into a state where we spend a few miliseconds doing a bunch of
> locking operations synchronously to figure out that there's nothing to
> do. Let's reorganize the code here a bit so that we don't grab the lock
> until we're actually going to do something so that suspend is a little
> faster.
>
> Cc: Matthias Kaehlcke <mka@chromium.org>
> Cc: Douglas Anderson <dianders@chromium.org>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
>  drivers/regulator/core.c | 75 +++++++++++++++++++++++++++-------------
>  1 file changed, 51 insertions(+), 24 deletions(-)

Looks good to me.  Agree that getting a pointer to the relevant
"struct regulator_state" and checking whether some details about it
and our ops should be safe to do without a lock.  Patch looks clean
and correct.

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] regulator: Avoid grabbing regulator lock during suspend/resume
  2020-08-04  7:08 [PATCH] regulator: Avoid grabbing regulator lock during suspend/resume Stephen Boyd
  2020-08-05  4:55 ` Doug Anderson
@ 2020-08-18 16:56 ` Mark Brown
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Brown @ 2020-08-18 16:56 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-kernel, Douglas Anderson, Matthias Kaehlcke, Liam Girdwood

On Tue, 4 Aug 2020 00:08:37 -0700, Stephen Boyd wrote:
> I see it takes about 5us per regulator to grab the lock, check that this
> regulator isn't going to do anything for suspend, and then release the
> lock. When that is combined with PMICs that have dozens of regulators we
> get into a state where we spend a few miliseconds doing a bunch of
> locking operations synchronously to figure out that there's nothing to
> do. Let's reorganize the code here a bit so that we don't grab the lock
> until we're actually going to do something so that suspend is a little
> faster.

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next

Thanks!

[1/1] regulator: Avoid grabbing regulator lock during suspend/resume
      commit: 0955f5be4337c0ada82e49389249eb99199f8db2

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-08-18 17:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-04  7:08 [PATCH] regulator: Avoid grabbing regulator lock during suspend/resume Stephen Boyd
2020-08-05  4:55 ` Doug Anderson
2020-08-18 16:56 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).