From patchwork Wed Sep 12 08:28:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 146520 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp4547095ljw; Wed, 12 Sep 2018 01:30:18 -0700 (PDT) X-Google-Smtp-Source: ANB0VdbcLaWwO/Mj+tXBJIH+ygyMcVV0dg1C9d/R0us2rM8V/hkdPBUUqjjBvJ7iDOqo/vL0KAgF X-Received: by 2002:a62:c90a:: with SMTP id k10-v6mr938958pfg.180.1536741018160; Wed, 12 Sep 2018 01:30:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536741018; cv=none; d=google.com; s=arc-20160816; b=bBp9br3fzRRXRPp4drm8yQz0+9dTIu9R0EtarPGzODf4wSiXdszqeB7WkVvYfkjmTc Pa6VrnRNmlHFJD82HON8rAk4MNF7etazVkgPn212GVE2QKjul43ZfeN1LhI7qw+WkIpz AGVZSqzqoDo7Qmpg4B7BpqV1/w0vScC/FoTROi5nasT4nGel4gl9uVnesdbO1bQtW+8Z TB/1tYZx56vIyflUOrhaNe+cy8QtXbWWo3rICkvdAfSOWZcjqtSTzXMwdDgfsxN3RmNw m/G8iJlomZbFIb8v23fQb2Ph2cAEQEF1OHkjsEujz74xlhPBLYsVWBS/WbP5ALFLZIHD uliA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=jLrWZpb9Eb/sZJFwJhTGcqYIBmyIgGhRRYN0pKoqWKA=; b=0gaS5JZR1mU4u2ZCngLY/pnuxVJstfVJEfeXJWsdplToZudOpoEiNv3+Uxx8XZbbQ3 zBcQFOMWa31D6vr9qzPLF+hm23cLtTN6zw2hL3ItBenfhsaUOe3YjzKLvI0R77Iua8Wq malBcMA5sOfc92ad25hblI2yOewVPsPPSCc6jccF/yr8R6qb1P8FUdknqhuhSIMb3EY4 zqxEY9nAE4HRQ/4rTAMQyiUX8gs49ooBlIGJtBuCfZF6HFHCywTVCCrHnNMKy7dL0vT7 +seP9vdvut1WSrIyZmejPIVJeAPnqH08QjRtMplNtZTeJH+AohzOf+fQHmQBBOdxtwBD ARqA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YmHC1PAZ; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s13-v6si366682pgo.505.2018.09.12.01.30.17; Wed, 12 Sep 2018 01:30:18 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YmHC1PAZ; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728166AbeILNdn (ORCPT + 10 others); Wed, 12 Sep 2018 09:33:43 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:45004 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727825AbeILNdn (ORCPT ); Wed, 12 Sep 2018 09:33:43 -0400 Received: by mail-pf1-f193.google.com with SMTP id k21-v6so637393pff.11 for ; Wed, 12 Sep 2018 01:30:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=jLrWZpb9Eb/sZJFwJhTGcqYIBmyIgGhRRYN0pKoqWKA=; b=YmHC1PAZOI5n6UI3VqrIHJ4p8xgMRpVnossmXm8Jle2pHl8PWXHaj36llHqDYiN2KB PTWnzcUG1cnAl/2AFFfkwKAffo6T1wja42+n6Z4OYgZnY2X4/TwfpsqJTujtGzdHsiqk DgbbHt4Xdmuum/ttnLST2kp98td8CPkDEc4Mc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jLrWZpb9Eb/sZJFwJhTGcqYIBmyIgGhRRYN0pKoqWKA=; b=uK+Jy9rPVE8FAKGTJF6ycT/Xk6s1e7xG6+5hGFCWIUzoUe+ktbykTnLY6YJxB05Pc2 fLXaqLOylxTZUx/wU4BNZSkaPa3m5cXP08vW4/ml+y8tp/x8OM7Pth2TIM250dJJVicZ MlGBq8XeLfjAG7MDogx+APS3MBN7EwhyCQccUKKKC+t6lCtu2W8g4ugJMchre1hut+gk XiRu1ogAJVtxj1N4BLSln21VqB648HgOVPAyRK6y1vX9McFMZaQdyrs6P3scgeOwE1bd DK0sznPuosJTRoaBzXgK8MoN1acy/W/LgU4YLm5raO4uhWiPwkMPtWwY6yqrQ3SNyzWW F+wQ== X-Gm-Message-State: APzg51A6Vi9bvYTowmFyfxdSOOxhmuOK8R1Go29s2P03a4Rbze+LHaFI oJrHH2YWhst4Yiq/PLyaMnKJMg== X-Received: by 2002:a62:5543:: with SMTP id j64-v6mr926879pfb.188.1536741015294; Wed, 12 Sep 2018 01:30:15 -0700 (PDT) Received: from localhost ([122.171.64.45]) by smtp.gmail.com with ESMTPSA id j16-v6sm1432654pfk.125.2018.09.12.01.30.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 12 Sep 2018 01:30:14 -0700 (PDT) From: Viresh Kumar To: niklas.cassel@linaro.org, Viresh Kumar , Nishanth Menon , Stephen Boyd Cc: Viresh Kumar , Rafael Wysocki , linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org Subject: [PATCH 09/11] OPP: Use a single mechanism to free the OPP table Date: Wed, 12 Sep 2018 13:58:48 +0530 Message-Id: X-Mailer: git-send-email 2.18.0.rc1.242.g61856ae69a2c In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Currently there are two separate ways to free the OPP table based on how it is created in the first place. We call _dev_pm_opp_remove_table() to free the static and/or dynamic OPP, OPP list devices, etc. This is done for the case where the OPP table is added while initializing the OPPs, like via the path dev_pm_opp_of_add_table(). We also call dev_pm_opp_put_opp_table() in some cases which eventually frees the OPP table structure once the reference count reaches 0. This is used by the first case as well as other cases like dev_pm_opp_set_regulators() where the OPPs aren't necessarily initialized at this point. This whole thing is a bit unclear and messy and obstruct any further cleanup/fixup of OPP core. This patch tries to streamline this by keeping a single path for OPP table destruction, i.e. dev_pm_opp_put_opp_table(). All the cleanup happens in _opp_table_kref_release() now after the reference count reaches 0. _dev_pm_opp_remove_table() is removed as it isn't required anymore. We don't drop the reference to the OPP table after creating it from _of_add_opp_table_v{1|2}() anymore and the same is dropped only when we try to remove them. Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 54 ++++++++++++++-------------------------------- drivers/opp/of.c | 32 +++++++++++++++------------ drivers/opp/opp.h | 2 +- 3 files changed, 35 insertions(+), 53 deletions(-) -- 2.18.0.rc1.242.g61856ae69a2c diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 2319ad4a0177..d3e33fd32694 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -867,23 +867,24 @@ struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, static void _opp_table_kref_release(struct kref *kref) { struct opp_table *opp_table = container_of(kref, struct opp_table, kref); - struct opp_device *opp_dev; + struct opp_device *opp_dev, *temp; /* Release clk */ if (!IS_ERR(opp_table->clk)) clk_put(opp_table->clk); - /* - * No need to take opp_table->lock here as we are guaranteed that no - * references to the OPP table are taken at this point. - */ - opp_dev = list_first_entry(&opp_table->dev_list, struct opp_device, - node); + WARN_ON(!list_empty(&opp_table->opp_list)); - _remove_opp_dev(opp_dev, opp_table); + list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) { + /* + * The OPP table is getting removed, drop the performance state + * constraints. + */ + if (opp_table->genpd_performance_state) + dev_pm_genpd_set_performance_state((struct device *)(opp_dev->dev), 0); - /* dev_list must be empty now */ - WARN_ON(!list_empty(&opp_table->dev_list)); + _remove_opp_dev(opp_dev, opp_table); + } mutex_destroy(&opp_table->lock); list_del(&opp_table->node); @@ -1758,33 +1759,6 @@ int dev_pm_opp_unregister_notifier(struct device *dev, } EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); -/* - * Free OPPs either created using static entries present in DT. - */ -void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev) -{ - /* Protect dev_list */ - mutex_lock(&opp_table->lock); - - /* Find if opp_table manages a single device */ - if (list_is_singular(&opp_table->dev_list)) { - /* Free static OPPs */ - _put_opp_list_kref(opp_table); - - /* - * The OPP table is getting removed, drop the performance state - * constraints. - */ - if (opp_table->genpd_performance_state) - dev_pm_genpd_set_performance_state(dev, 0); - } else { - _put_opp_list_kref(opp_table); - _remove_opp_dev(_find_opp_dev(dev, opp_table), opp_table); - } - - mutex_unlock(&opp_table->lock); -} - void _dev_pm_opp_find_and_remove_table(struct device *dev) { struct opp_table *opp_table; @@ -1802,8 +1776,12 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev) return; } - _dev_pm_opp_remove_table(opp_table, dev); + _put_opp_list_kref(opp_table); + + /* Drop reference taken by _find_opp_table() */ + dev_pm_opp_put_opp_table(opp_table); + /* Drop reference taken while the OPP table was added */ dev_pm_opp_put_opp_table(opp_table); } diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 9c98682af374..a5cba0234220 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -407,14 +407,17 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, opp_table = _managed_opp(opp_np); if (opp_table) { /* OPPs are already managed */ - if (!_add_opp_dev(dev, opp_table)) + if (!_add_opp_dev(dev, opp_table)) { ret = -ENOMEM; - else if (!opp_table->parsed_static_opps) - goto initialize_static_opps; - else + goto put_opp_table; + } + + if (opp_table->parsed_static_opps) { kref_get(&opp_table->list_kref); + return 0; + } - goto put_opp_table; + goto initialize_static_opps; } opp_table = dev_pm_opp_get_opp_table_indexed(dev, index); @@ -432,17 +435,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, if (ret) { dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, ret); - _dev_pm_opp_remove_table(opp_table, dev); of_node_put(np); - goto put_opp_table; + goto put_list_kref; } } /* There should be one of more OPP defined */ if (WARN_ON(!count)) { ret = -ENOENT; - _put_opp_list_kref(opp_table); - goto put_opp_table; + goto put_list_kref; } list_for_each_entry(opp, &opp_table->opp_list, node) @@ -453,8 +454,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", count, pstate_count); ret = -ENOENT; - _dev_pm_opp_remove_table(opp_table, dev); - goto put_opp_table; + goto put_list_kref; } if (pstate_count) @@ -462,6 +462,10 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, opp_table->parsed_static_opps = true; + return 0; + +put_list_kref: + _put_opp_list_kref(opp_table); put_opp_table: dev_pm_opp_put_opp_table(opp_table); @@ -507,13 +511,13 @@ static int _of_add_opp_table_v1(struct device *dev) if (ret) { dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", __func__, freq, ret); - _dev_pm_opp_remove_table(opp_table, dev); - break; + _put_opp_list_kref(opp_table); + dev_pm_opp_put_opp_table(opp_table); + return ret; } nr -= 2; } - dev_pm_opp_put_opp_table(opp_table); return ret; } diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 3b1d94748a4d..b260fb7b307a 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -190,11 +190,11 @@ struct opp_table { /* Routines internal to opp core */ void dev_pm_opp_get(struct dev_pm_opp *opp); +void _opp_remove_all_static(struct opp_table *opp_table); void _get_opp_table_kref(struct opp_table *opp_table); int _get_opp_count(struct opp_table *opp_table); struct opp_table *_find_opp_table(struct device *dev); struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table); -void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev); void _dev_pm_opp_find_and_remove_table(struct device *dev); struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table); void _opp_free(struct dev_pm_opp *opp);