Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755486AbbB0VBh (ORCPT ); Fri, 27 Feb 2015 16:01:37 -0500 Received: from bhuna.collabora.co.uk ([93.93.135.160]:56958 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754632AbbB0VBe (ORCPT ); Fri, 27 Feb 2015 16:01:34 -0500 Message-ID: <54F0DB23.3010203@collabora.co.uk> Date: Fri, 27 Feb 2015 22:01:23 +0100 From: Javier Martinez Canillas User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.2.0 MIME-Version: 1.0 To: Doug Anderson , Mark Brown CC: milo.kim@ti.com, axel.lin@ingics.com, Dmitry Torokhov , olof@lixom.net, Paul Stewart , stable@vger.kernel.org, lgirdwood@gmail.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH] regulator: core: Fix enable GPIO reference counting References: <1425066064-18920-1-git-send-email-dianders@chromium.org> In-Reply-To: <1425066064-18920-1-git-send-email-dianders@chromium.org> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4227 Lines: 110 Hello Doug, On 02/27/2015 08:41 PM, Doug Anderson wrote: > It is possible for _regulator_do_enable() to be called for an > already-enabled rdev, like in regulator_suspend_finish(). If we were > using an enable pin (rdev->ena_pin is set) then we'd end up > incrementing the reference count in regulator_ena_gpio_ctrl() over and > over again without a decrement. That prevented the GPIO from going to > the "off" state even after all users were disabled. > > Fix this by avoiding the call to regulator_ena_gpio_ctrl() when it's > not needed. > I noticed the same problem in regulator_suspend_finish() when I was working on S2R for Exynos a couple of months ago and had patch [0] on my local tree but never found the time to do extensive testing so I never posted it. In my case a tps65090 FET regulator was tried to be enabled twice and tps65090_fet_enable() was failing printing a warning. > Signed-off-by: Doug Anderson > Fixes: 967cfb18c0e3 ("regulator: core: manage enable GPIO list") > --- > FYI: this was developed and tested against a 3.14 kernel with > backports; I've done basic boot testing against upstream and sanity > checked the code but haven't done as extensive testing there. > > drivers/regulator/core.c | 20 ++++++++++++-------- > 1 file changed, 12 insertions(+), 8 deletions(-) > > diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c > index b899947..9daccbb 100644 > --- a/drivers/regulator/core.c > +++ b/drivers/regulator/core.c > @@ -1839,10 +1839,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev) > } > > if (rdev->ena_pin) { > - ret = regulator_ena_gpio_ctrl(rdev, true); > - if (ret < 0) > - return ret; > - rdev->ena_gpio_state = 1; > + if (!rdev->ena_gpio_state) { > + ret = regulator_ena_gpio_ctrl(rdev, true); > + if (ret < 0) > + return ret; > + rdev->ena_gpio_state = 1; > + } > } else if (rdev->desc->ops->enable) { > ret = rdev->desc->ops->enable(rdev); > if (ret < 0) Your approach to check in _regulator_do_enable() is more generic though since it covers future issues and not only regulator_suspend_finish() but otoh it only cover the case for GPIO enabled regulators so you may also check for other type of regulators using _regulator_is_enabled()? I see that the check is already in _regulator_enable() so another option is to call _regulator_enable() instead of _regulator_do_enable() in regulator_suspend_finish(). Best regards, Javier [0]: >From 71bb25eff5c2aac4a7b6878f205f3f8905c61363 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 16 Oct 2014 01:31:20 +0100 Subject: [PATCH 1/1] regulator: Only enable disabled regulators on resume After leaving from system wide suspend state, regulator_suspend_finish() turn on regulators that might be turned off by regulator_suspend_prepare but it tries to enable all regulators that have an enable count > 0 or that were marked as "always-on" regardless if those were disabled or not. Trying to enable an already enabled regulator may cause issues so is better to skip enabling regulators that were not disabled before suspend. Signed-off-by: Javier Martinez Canillas --- drivers/regulator/core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f2452148c8da..4f1932aa10bc 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3816,9 +3816,11 @@ int regulator_suspend_finish(void) list_for_each_entry(rdev, ®ulator_list, list) { mutex_lock(&rdev->mutex); if (rdev->use_count > 0 || rdev->constraints->always_on) { - error = _regulator_do_enable(rdev); - if (error) - ret = error; + if (!_regulator_is_enabled(rdev)) { + error = _regulator_do_enable(rdev); + if (error) + ret = error; + } } else { if (!have_full_constraints()) goto unlock; -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/