From patchwork Wed Sep 19 22:20:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 147054 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp1233043ljw; Wed, 19 Sep 2018 15:20:59 -0700 (PDT) X-Google-Smtp-Source: ANB0VdYImI1m0iOXoQ/GEwsPRSZa90eLubMYUZco3ACi+37IX8Y80/7EqsexHZi89Qxoz49XSh2F X-Received: by 2002:a17:902:1566:: with SMTP id b35-v6mr36097318plh.135.1537395659752; Wed, 19 Sep 2018 15:20:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537395659; cv=none; d=google.com; s=arc-20160816; b=T2N5BoP3xQTAjqTTPdM8ODuIGl8BxfaWn6kSwpyJwVAn7L4xkbdrS+D5du/Rh4dxgT Yyvn/WwQ0Kj91nPscZjUprEr180bNilNA1wFt4r0SL6Q9fKFAnYjMJGuCkH6kd0DkI6R mm8oH4wCXyBD0H92dvQIPKhFJr2JLb6OUHf/PLltDKSB/vjLOkLcrBDrIVDr7rgIb6rA MuK6DuHXB8aWHvLvyf/TW2f2d4uw24xoxgb8ZxIUM5EJYfNreV07DstrDkNOOp6++1ET wwYJGMQxc+Z6ato5vHLD9wMzIlyf0VIrwNAVw/tqE5g3yp5MS3tu0Sj6/B0/uaGV5M0a oyDA== 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:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=HX5eDqLq6MnZX9E6B4v/vOFT0a/x+hzpVnpPDmao/5Y=; b=dekf8ruSsndW1zB60ktYISyrmE+lGcTr8Z9nqGjXUJP8v3Zn5g072rBf5QM9C2VSN9 wWCkeWPAa+2MEilatawQmKCvrja7+Si+ObD9j2fO3vEx1N7Gqbff2faXkgc4KwiNlhd+ 2vzdYrswtTzfJB9qAU4IArOj2dSjWk1AYpekZvGKDlM/CmNCjVpnqHd3o3qLd76N4Sam y4977krmITarzmKN+Vaf12gh5mAU5XVXfKlJMlzaAyYhHGxs+mCTwGJZoSNd+zAQC3t4 7qBJ/HAx5X86lEd/VreBlX9Annjd1T9L+/ntNCeMtBpKVQejFJG/STB/ObwU+BA30f42 DDsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=iVliWPLg; 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 n8-v6si22034915pgl.101.2018.09.19.15.20.57; Wed, 19 Sep 2018 15:20:59 -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=iVliWPLg; 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 S2387432AbeITEA4 (ORCPT + 32 others); Thu, 20 Sep 2018 00:00:56 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:38946 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387399AbeITEAy (ORCPT ); Thu, 20 Sep 2018 00:00:54 -0400 Received: by mail-pl1-f193.google.com with SMTP id w14-v6so3300416plp.6 for ; Wed, 19 Sep 2018 15:20:53 -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 :in-reply-to:references; bh=HX5eDqLq6MnZX9E6B4v/vOFT0a/x+hzpVnpPDmao/5Y=; b=iVliWPLgAZaeCvinWz/oXkCKCEBJw1rChrOeNhddY1LOHXqe/CHuwAQXYj44J7S12i 25l3DV1zAWvCPZDDN2CY767iL2caYnqVIbfSnFHr2mi9KdLXlxPYhe3FgFRarJGxxYIf F4zcVTyNjt0kBVeOH86pNmt/0oVYwvXw5XY0Q= 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:in-reply-to:references; bh=HX5eDqLq6MnZX9E6B4v/vOFT0a/x+hzpVnpPDmao/5Y=; b=ncWtmbuuNw6yI9sQXeJbqS1RX1ifM8h4n9WJEEIChyrGLuNw5rdC/F8QJEWwCcGFz8 dm1gnyLpjX93O8JQh46TWOaiYemeSQiPoMsMkO/9TVP8ZPcbP3Cnx2+7GrfYnF7wvSzG oGI0HwPIWzNg2GZbemJKSXBdt06gQa1Z7V74DWbF20YQEqX5NEe1Hhb/eTLTXx0PxZkF 4xIzVLdo8XH4UOO7GKLuCwqJS/V1mgmQFVhUrbu7vWnQWJeCL790kOzqjZB1isYtydEf RgY8zkLAUqL+E3aWzbV+ARR8MPje2stqtu47ejwVSaeNS0ZOir81fQvF9Yqhkyuy3PYG r2rg== X-Gm-Message-State: APzg51DVTQoMmBK31zkMAIu8jIvyDm0S4U7uEkK3kHkpdH2IA2Ib8X18 P7yc0s8OfrvUPl7yUorqz0Kvaw== X-Received: by 2002:a17:902:e281:: with SMTP id cf1-v6mr36276933plb.86.1537395653568; Wed, 19 Sep 2018 15:20:53 -0700 (PDT) Received: from localhost ([209.121.128.187]) by smtp.gmail.com with ESMTPSA id x9-v6sm33824822pfd.31.2018.09.19.15.20.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 19 Sep 2018 15:20:52 -0700 (PDT) From: Viresh Kumar To: Viresh Kumar , Nishanth Menon , Stephen Boyd Cc: Viresh Kumar , Rafael Wysocki , linux-pm@vger.kernel.org, Vincent Guittot , Niklas Cassel , linux-kernel@vger.kernel.org Subject: [PATCH V2 07/12] OPP: Create separate kref for static OPPs list Date: Wed, 19 Sep 2018 15:20:26 -0700 Message-Id: X-Mailer: git-send-email 2.14.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@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. Tested-by: Niklas Cassel 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.14.1 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 4a19f76880d3..aaa4bab69846 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 b04c2b511c4d..9274116c90e4 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, int last_cpu); 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);