Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp5140018imm; Wed, 12 Sep 2018 01:32:08 -0700 (PDT) X-Google-Smtp-Source: ANB0VdaQbM2W5PtNV3pcf75MhohjvxUi9sUtWnbUjR1a7+/YM14My5qg5xB37wHCk+tV0vTpkQCl X-Received: by 2002:a63:a745:: with SMTP id w5-v6mr904349pgo.374.1536741128210; Wed, 12 Sep 2018 01:32:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536741128; cv=none; d=google.com; s=arc-20160816; b=xkRPZy7qkuY4akJjok2Fs2vpTqLS4eMclcfw9iEYhaRBq/1ydsKvkvdSrxnlwqwCYu im877wTrH6sn2g3WstPAvLf7UobDZrifV10JaABUDPspbzm44Qzv+h0zO5mq6eLt5522 0d+I//nWdCmd36ecRzEtUndW0a3u3Ed3TLXKWPmSlf7nPDhoqIs19fgvykIDnM6D1f55 NOI7FZB2LdeiG/7nNgKT64LT0OwgEolhhVK1s9j9F5ZmRTCm9RrrcrYHCo/DhS3dkbcu gs/HfXZsYPy299ZxsYIy2qj/dRJZ3o5q3VKEvay74d4tceO7OHlMVDL93GxmfeLgwe1i CoNA== 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=QpRHu3ieWwt2sg2UqDk4plst2mH4Vzd33p24p/UlEu9TkX/tPCv/LyxvXQ0ehjyryM ENXBZFH6sL8T4hDNJZnRuJ7mXpZ96xRJlPzTxYhA91+fWEI5m4YoiPqIoZpASuGasfmd xka58a9EOBVmr1dntJP6G2dXctVkizm0s86pEFLWLm2RoogA/R0zibegMFJE4IO5IQXW BA/kWv0p0TcGcDmz8y3oMjGHdeXb8PebfmAUFJiZPbwnXBPzag+VxkPXkVxIjTFdk12y sF4EGW362xDT3in/sPDjzHC8wPuCEoHAcOB8UPFd6WrRUMq4m5jO/Y6scP0hunRquibx MeVg== 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-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 88-v6si364493plc.515.2018.09.12.01.31.52; Wed, 12 Sep 2018 01:32:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-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-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 S1728196AbeILNdp (ORCPT + 99 others); Wed, 12 Sep 2018 09:33:45 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:42811 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727834AbeILNdn (ORCPT ); Wed, 12 Sep 2018 09:33:43 -0400 Received: by mail-pg1-f194.google.com with SMTP id y4-v6so663176pgp.9 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=RoYXj6MqClYBLymmmGMcsBXeXHG9fsIsULWvYiOyukjyG24uYm++akjF3tIvPSluvK mGfjL8i4jGi7unGQGU2+lNkB0/KOvvvompJpRuShQGOD4dtdG3vGdwvfnaArJH1SxmlH 9qcdK9lCVNCMFXuzOwACjsBPa66K3stf7pneT7HhmwvMKQDmhUihZbFPikIgZmd2m2Y3 7Vdm0GeLNstuQy27+XCJT5GthtAbBIydSvkivicoMSjJJ7itIpgtv+9uIALCUmO7N5TA 7iib/ibMUpudMYhpFWjmdHq8UATxvElCrI+nmcNqfd7KZlqEfW/6NV7BtQJBi2r869DA vaXg== X-Gm-Message-State: APzg51CPuYZxeWyhNpg2PAY5ya1AiAQCb1f/Ytyhrr8nlDPFvS12WlMc xBt+mBwozkcerokB+KImP6LSwQ== 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-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@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(-) 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); -- 2.18.0.rc1.242.g61856ae69a2c