From patchwork Wed Mar 25 01:56:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 6087261 Return-Path: X-Original-To: patchwork-linux-arm@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 B0D539F2A9 for ; Wed, 25 Mar 2015 01:59:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C61A720263 for ; Wed, 25 Mar 2015 01:59:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B89E320148 for ; Wed, 25 Mar 2015 01:59:33 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YaaYj-00050p-9e; Wed, 25 Mar 2015 01:56:41 +0000 Received: from seldrel01.sonyericsson.com ([212.209.106.2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YaaYg-0004wV-19 for linux-arm-kernel@lists.infradead.org; Wed, 25 Mar 2015 01:56:38 +0000 From: Bjorn Andersson To: Liam Girdwood , Mark Brown Subject: [PATCH] regulator: Defer lookup of supply to regulator_get Date: Tue, 24 Mar 2015 18:56:05 -0700 Message-ID: <1427248565-9680-1-git-send-email-bjorn.andersson@sonymobile.com> X-Mailer: git-send-email 1.8.2.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150324_185638_267485_23D7829B X-CRM114-Status: GOOD ( 17.59 ) X-Spam-Score: -5.0 (-----) Cc: linux-arm-msm@vger.kernel.org, Stephen Boyd , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_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 Instead of resolving regulator supplies during registration move this to the time of a consumer retrieving a handle. The benefit is that it's possible for one driver to register regulators with internal dependencies out of order. Signed-off-by: Bjorn Andersson --- drivers/regulator/core.c | 92 ++++++++++++++++++++++++---------------- include/linux/regulator/driver.h | 1 + 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f245214..52ddb73 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1325,6 +1325,54 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, return NULL; } +static int regulator_resolve_supply(struct regulator_dev *rdev) +{ + struct regulator_dev *r; + struct device *dev = rdev->dev.parent; + int ret; + + /* No supply to resovle? */ + if (!rdev->supply_name) + return 0; + + /* Supply already resolved? */ + if (rdev->supply) + return 0; + + r = regulator_dev_lookup(dev, rdev->supply_name, &ret); + if (ret == -ENODEV) { + /* + * No supply was specified for this regulator and + * there will never be one. + */ + return 0; + } + + if (!r) { + dev_err(dev, "Failed to resolve %s-supply for %s\n", + rdev->supply_name, rdev->desc->name); + return -EPROBE_DEFER; + } + + /* Recursively resolve the supply of the supply */ + ret = regulator_resolve_supply(r); + if (ret < 0) + return ret; + + ret = set_supply(rdev, r); + if (ret < 0) + return ret; + + /* Cascade always-on state to supply */ + if (_regulator_is_enabled(rdev)) { + ret = regulator_enable(rdev->supply); + if (ret < 0) + return ret; + } + + return 0; +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, bool exclusive, bool allow_dummy) @@ -1394,6 +1442,12 @@ found: goto out; } + ret = regulator_resolve_supply(rdev); + if (ret < 0) { + regulator = ERR_PTR(ret); + goto out; + } + if (!try_module_get(rdev->owner)) goto out; @@ -3545,7 +3599,6 @@ regulator_register(const struct regulator_desc *regulator_desc, struct regulator_dev *rdev; struct device *dev; int ret, i; - const char *supply = NULL; if (regulator_desc == NULL || cfg == NULL) return ERR_PTR(-EINVAL); @@ -3659,41 +3712,10 @@ regulator_register(const struct regulator_desc *regulator_desc, goto scrub; if (init_data && init_data->supply_regulator) - supply = init_data->supply_regulator; + rdev->supply_name = init_data->supply_regulator; else if (regulator_desc->supply_name) - supply = regulator_desc->supply_name; - - if (supply) { - struct regulator_dev *r; - - r = regulator_dev_lookup(dev, supply, &ret); + rdev->supply_name = regulator_desc->supply_name; - if (ret == -ENODEV) { - /* - * No supply was specified for this regulator and - * there will never be one. - */ - ret = 0; - goto add_dev; - } else if (!r) { - dev_err(dev, "Failed to find supply %s\n", supply); - ret = -EPROBE_DEFER; - goto scrub; - } - - ret = set_supply(rdev, r); - if (ret < 0) - goto scrub; - - /* Enable supply if rail is enabled */ - if (_regulator_is_enabled(rdev)) { - ret = regulator_enable(rdev->supply); - if (ret < 0) - goto scrub; - } - } - -add_dev: /* add consumers devices */ if (init_data) { for (i = 0; i < init_data->num_consumer_supplies; i++) { @@ -3720,8 +3742,6 @@ unset_supplies: unset_regulator_supplies(rdev); scrub: - if (rdev->supply) - _regulator_put(rdev->supply); regulator_ena_gpio_free(rdev); kfree(rdev->constraints); wash: diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 0f86a182..a15c59d 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -371,6 +371,7 @@ struct regulator_dev { struct device dev; struct regulation_constraints *constraints; struct regulator *supply; /* for tree */ + const char *supply_name; struct regmap *regmap; struct delayed_work disable_work;