From patchwork Wed Sep 12 08:28:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 146517 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp4546929ljw; Wed, 12 Sep 2018 01:30:08 -0700 (PDT) X-Google-Smtp-Source: ANB0VdavfroNTv8h9oz2CXuYfO7N0H0556VwO5m5Grf4XOn9Q5a2KnVuwnlurV6idlm73So7e55q X-Received: by 2002:a62:225d:: with SMTP id i90-v6mr930879pfi.246.1536741008317; Wed, 12 Sep 2018 01:30:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536741008; cv=none; d=google.com; s=arc-20160816; b=lAxDLbEsHXm5h5CS+mZlhIJi0oLYAeNFYg2asGN+zXHIQZFMtUKZWPgsbe2LTWhJbQ fNC9k4hTkamPM9VQv7k5lrtujPitd3l6U7XnnIEWuCwUTXSWpVYXtUMWr/PCeuy3vNwJ VEhpYD1CUHcw9b6VZnDkm4rhHzxqo0Gh173ioWLXfQ2JQgIdfTscTbhrVf2J8pHxPMdq J6ERE1uNt9/1db6EoB527iIGPHMcZ/4GKim8JbosWUdIQ98Vt9dFr087HqeRNK4JTJK5 uoQRHL2xLKpSJ3HUlTUvmi5mzZiabkWwt3jJI/fayOFxSbLMTwTK8eFeMB8B7O0xMNCV rnLQ== 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=bOqb8Y/Ki92J5bVwFaxRmefkd408CdxSloxrbWIZXp8=; b=neXssT21Jgn/UOIpKOZoMkAgtuXSYEHdFhzwggMy13QEYLp0x5/EbmYOlBNKodgVlY AgQvV6EkBJMuUy7rpn/QvRnMTyMSxgZXqgKEeCbCSJey2Y7KGlMxPbHuDN01CnsIYxHs 3Q99D7SeQvyBUKHEsQsyvKuan24Ys36lTRANrnKJ4sZZYXWZ45vnci4Y2A2yV8mO5+HP 0Ga/olhEiQqD0DbP0xvaBrjWbjC54OxDfQVY29zx6PViOTPNKPV/K3qwVuj2ong5UKJp ZapRexCucRvqfOgmjRQXJpDEis7Eg7Ggmsg8SH3B6heu3k6oORcYM08BAPncFfJoCstE jQVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=E4a4JHHF; 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 s71-v6si363611pgs.499.2018.09.12.01.30.08; Wed, 12 Sep 2018 01:30:08 -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=E4a4JHHF; 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 S1728094AbeILNde (ORCPT + 10 others); Wed, 12 Sep 2018 09:33:34 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:41818 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728090AbeILNdd (ORCPT ); Wed, 12 Sep 2018 09:33:33 -0400 Received: by mail-pl1-f196.google.com with SMTP id b12-v6so620657plr.8 for ; Wed, 12 Sep 2018 01:30:06 -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=bOqb8Y/Ki92J5bVwFaxRmefkd408CdxSloxrbWIZXp8=; b=E4a4JHHFS0WobIR2+BcmYpszw/c/1g7azPbMpoGJwlWdpQrEJ3YzrvcA+bk1N8WTje is2DwvZR8+vGHkRPuqk46vO+GYzNQMmQUIk8C33EbDRHduliE/ZyDWdrjWRo/bOo5mfH YhJc5mj4WdiPqiiLk1GW3qr4+sZovlmGtEm4E= 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=bOqb8Y/Ki92J5bVwFaxRmefkd408CdxSloxrbWIZXp8=; b=UVgGbkyayURVdevwTq7BmEMj4pwGNdZND/UpJKA5u4O5jGv/SCb9pI7HbozgvqFow+ GkxWVbXZfmcTfxZ3U8QEeeFRoE03JBTHdZLdpPrWwsVuU94E5eV7SuFXgxDz88pH1bVz 30HQ5k5K4JnxdQk7OLhN0t96OgoY4coa246+VTXQFT2f8dZCDxMjKlWcXhLqF9bMqg72 6deDcUyBGQ94qIGUUKveQT8zP9ZWulg7ZOZRR7zWWqXo8xFMCSWi3+LlRrbVy9Fb8HJV Xilq9/D8N3kpqBglR/tB0Ap0oGHaUyTQOYTwUNwP9Ojcsabg4ERitObklXKEq/ftQl98 MeVQ== X-Gm-Message-State: APzg51B51gyHO6lzro5r84rEryda8bk+kNaEjWkBNkMp1rMNde/aaEHV LFaSZTa2fEmNRiSrpfpnIt4sGA== X-Received: by 2002:a17:902:5a87:: with SMTP id r7-v6mr874291pli.247.1536741005892; Wed, 12 Sep 2018 01:30:05 -0700 (PDT) Received: from localhost ([122.171.64.45]) by smtp.gmail.com with ESMTPSA id f87-v6sm1147545pfh.168.2018.09.12.01.30.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 12 Sep 2018 01:30:05 -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 06/11] OPP: Create separate kref for static OPPs list Date: Wed, 12 Sep 2018 13:58:45 +0530 Message-Id: <42981293f33d4baf752f7629f41625f009b3cebb.1536736872.git.viresh.kumar@linaro.org> 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 The static OPPs don't always get freed with the OPP table, it can happen before that as well. For example, if the OPP table is first created using helpers like dev_pm_opp_set_supported_hw() and the OPPs are created at a later point. Now when the OPPs are removed, the OPP table stays until the time dev_pm_opp_put_supported_hw() is called. Later patches will streamline the freeing of OPP table and that requires the static OPPs to get freed with help of a separate kernel reference. This patch prepares for that by creating a separate kref for static OPPs list. Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 33 ++++++++++++++++++++++++++++++++- drivers/opp/of.c | 7 +++++++ drivers/opp/opp.h | 3 +++ 3 files changed, 42 insertions(+), 1 deletion(-) -- 2.18.0.rc1.242.g61856ae69a2c diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 2a6976265580..b555121b878b 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -892,6 +892,33 @@ static void _opp_table_kref_release(struct kref *kref) mutex_unlock(&opp_table_lock); } +void _opp_remove_all_static(struct opp_table *opp_table) +{ + struct dev_pm_opp *opp, *tmp; + + list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) { + if (!opp->dynamic) + dev_pm_opp_put(opp); + } + + opp_table->parsed_static_opps = false; +} + +static void _opp_table_list_kref_release(struct kref *kref) +{ + struct opp_table *opp_table = container_of(kref, struct opp_table, + list_kref); + + _opp_remove_all_static(opp_table); + mutex_unlock(&opp_table_lock); +} + +void _put_opp_list_kref(struct opp_table *opp_table) +{ + kref_put_mutex(&opp_table->list_kref, _opp_table_list_kref_release, + &opp_table_lock); +} + void dev_pm_opp_put_opp_table(struct opp_table *opp_table) { kref_put_mutex(&opp_table->kref, _opp_table_kref_release, @@ -1746,8 +1773,11 @@ void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, /* 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); + + /* Free dynamic OPPs */ list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) { - if (remove_all || !opp->dynamic) + if (remove_all) dev_pm_opp_put(opp); } @@ -1758,6 +1788,7 @@ void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, 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); } diff --git a/drivers/opp/of.c b/drivers/opp/of.c index ebf467b4d99e..892d17069f05 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -411,6 +411,8 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, ret = -ENOMEM; else if (!opp_table->parsed_static_opps) goto initialize_static_opps; + else + kref_get(&opp_table->list_kref); goto put_opp_table; } @@ -420,6 +422,8 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, return -ENOMEM; initialize_static_opps: + kref_init(&opp_table->list_kref); + /* We have opp-table node now, iterate over it and add OPPs */ for_each_available_child_of_node(opp_np, np) { count++; @@ -437,6 +441,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, /* There should be one of more OPP defined */ if (WARN_ON(!count)) { ret = -ENOENT; + _put_opp_list_kref(opp_table); goto put_opp_table; } @@ -491,6 +496,8 @@ static int _of_add_opp_table_v1(struct device *dev) if (!opp_table) return -ENOMEM; + kref_init(&opp_table->list_kref); + val = prop->value; while (nr) { unsigned long freq = be32_to_cpup(val++) * 1000; diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index d218fc0a498d..783428fa9c33 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -126,6 +126,7 @@ enum opp_table_access { * @dev_list: list of devices that share these OPPs * @opp_list: table of opps * @kref: for reference count of the table. + * @list_kref: for reference count of the OPP list. * @lock: mutex protecting the opp_list and dev_list. * @np: struct device_node pointer for opp's DT node. * @clock_latency_ns_max: Max clock latency in nanoseconds. @@ -157,6 +158,7 @@ struct opp_table { struct list_head dev_list; struct list_head opp_list; struct kref kref; + struct kref list_kref; struct mutex lock; struct device_node *np; @@ -200,6 +202,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *o int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic); void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of); struct opp_table *_add_opp_table(struct device *dev); +void _put_opp_list_kref(struct opp_table *opp_table); #ifdef CONFIG_OF void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index); 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);