From patchwork Wed Sep 19 22:20:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 147059 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp1233295ljw; Wed, 19 Sep 2018 15:21:15 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdaz8t0Lhb6/iDxzksNxmAoyDcjXyPQL9Odg/yCLh6YnPa8vKBQF/Pdt6MWo8ot3XnMadnJh X-Received: by 2002:a63:24c4:: with SMTP id k187-v6mr34401879pgk.162.1537395675204; Wed, 19 Sep 2018 15:21:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537395675; cv=none; d=google.com; s=arc-20160816; b=Npaau7RKktrlu93uNI4ikX5qQ7NPXaV7MY2uo+3dUvcy1qr/ras/PyeHNMfOIMv0j1 t64qfhbbp7InolhmEADznoK4AH74MLTnNose2umHuTTQIfrImqFz1Fx4Ztq3lHEhlwP/ jAOB5eFT+CK+GM/wWfBPaYXi0QSxUUItvPEW4/9d8Yt5Hq4qSv/hxuOPpHTnrDSbFtWB ADVQOzew19vAQEPfTuU7B2gQiCJ7EeMdXtkni/8a6i0VXUwGlEIT6p2ZlKgsL5UfPYhT GHL3FzJobumveir/0YZKfFy3ucREtGXncEG124E+ivlRyw0oKMux+JGeU9kEuCLPxL2S Wmig== 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=rxiJu/KT0VOL6VfChRrYVDga8+0QfxrCXpVuzdXnBO4=; b=bqCYfgQDBoW7kgp58CokUh+JlIJkvNWCK4EfzeSeIavrDALTReirZIpvQcKweKNAIV N1BKDSPT9ZlQNZrIYhYcM3Z8f4OFg03ZdwpluAsjrKkNUG8E78Vu25f2xa43yd+cinlO 4TO362o2WmTg3l3M3yVUsaDIMtPs8T8cACYFiMug23qm7005tMzDeEuJgQd+J1wbcsLI HHv35lfdj8xhkKjqd6uFLdaT9T5KhGGueTG06i6ORGyUxTejBcjYxIDh7HyZD7WqsN91 uWscUfqM4914GFli9Beq5Ui+/UOr2sNOR+YYKrBilme2kNBDRSK1gt9XCvhLSaqEvL9i WBvg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ikzmAEGB; 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 q28-v6si22116431pgm.689.2018.09.19.15.21.14; Wed, 19 Sep 2018 15:21:15 -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=ikzmAEGB; 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 S2387504AbeITEBB (ORCPT + 10 others); Thu, 20 Sep 2018 00:01:01 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:34567 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387462AbeITEBB (ORCPT ); Thu, 20 Sep 2018 00:01:01 -0400 Received: by mail-pl1-f193.google.com with SMTP id f6-v6so3310601plo.1 for ; Wed, 19 Sep 2018 15:21:00 -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=rxiJu/KT0VOL6VfChRrYVDga8+0QfxrCXpVuzdXnBO4=; b=ikzmAEGB42Zj3XDq48lFhnbEIA+c4LuNJVaQsujEHiXSx6BS3+oapROn/ZkNBKiMsm wL4GwkY2G66JLWmNNyTaeOCduCVoUZmepJKZnaevA7P+ckL6+5JviKqvH9Zx+I9CsaJi hdOJHWpo9kSX+XGRMIkbSJyIAzaYlAjN9Ktm0= 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=rxiJu/KT0VOL6VfChRrYVDga8+0QfxrCXpVuzdXnBO4=; b=Wb9RG+B1i7LYxb3bo+obCDkXRYT1/Laowe2Ad2Zrv0oRN7DpVEU5ax/Qvb0955EXb6 85mJROgR2Q4M5qRsgMkl2d9zef/4VQD8eSFoXxj3aew67qEwCCW/1qw6UAbVZ1lubNbf YAQDGw4YlMtxTPtz/zBC+IKO8b6FQbGn9YQWqScJi8hmFvnHriCrCIlz+nBX2Zj31sj9 8bWkflWtLXeNqAnqVU2UzVjGXGRMerbd1KVmXtLqdnr48djac7MeiwyvFsuNZWLStssO 1oBIgJD0sfnRYrcZK5tTPZrVAC+Z3C2fvsm6YYFIRJWSkqDIyrbgUYPbxo2By6sjuQO/ rwNQ== X-Gm-Message-State: APzg51B6/mOChFXFJqzhzkVMRGQt8xflgNX3XSirKVAF6rTey2Q2v9GI neUql14BJpUeW2k6/ccRPJrOVA== X-Received: by 2002:a17:902:8a92:: with SMTP id p18-v6mr36016518plo.148.1537395660158; Wed, 19 Sep 2018 15:21:00 -0700 (PDT) Received: from localhost ([209.121.128.187]) by smtp.gmail.com with ESMTPSA id w81-v6sm41086185pfk.92.2018.09.19.15.20.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 19 Sep 2018 15:20:59 -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 11/12] OPP: Prevent creating multiple OPP tables for devices sharing OPP nodes Date: Wed, 19 Sep 2018 15:20:30 -0700 Message-Id: X-Mailer: git-send-email 2.14.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org When two or more devices are sharing their clock and voltage rails, they share the same OPP table. But there are some corner cases where the OPP core incorrectly creates separate OPP tables for them. For example, CPU 0 and 1 share clock/voltage rails. The platform specific code calls dev_pm_opp_set_regulators() for CPU0 and the OPP core creates an OPP table for it (the individual OPPs aren't initialized as of now). The same is repeated for CPU1 then. Because _opp_get_opp_table() doesn't compare DT node pointers currently, it fails to find the link between CPU0 and CPU1 and so creates a new OPP table. Fix this by calling _managed_opp() from _opp_get_opp_table(). _managed_opp() gain an additional argument (index) to get the right node pointer. This resulted in simplifying code in _of_add_opp_table_v2() as well. Tested-by: Niklas Cassel Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 25 ++++++++++++++++++++++--- drivers/opp/of.c | 35 +++++++++++++---------------------- drivers/opp/opp.h | 2 ++ 3 files changed, 37 insertions(+), 25 deletions(-) -- 2.14.1 diff --git a/drivers/opp/core.c b/drivers/opp/core.c index d3e33fd32694..aaef20cf4df2 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -759,8 +759,8 @@ static void _remove_opp_dev(struct opp_device *opp_dev, kfree(opp_dev); } -struct opp_device *_add_opp_dev(const struct device *dev, - struct opp_table *opp_table) +struct opp_device *_add_opp_dev_unlocked(const struct device *dev, + struct opp_table *opp_table) { struct opp_device *opp_dev; int ret; @@ -772,7 +772,6 @@ struct opp_device *_add_opp_dev(const struct device *dev, /* Initialize opp-dev */ opp_dev->dev = dev; - mutex_lock(&opp_table->lock); list_add(&opp_dev->node, &opp_table->dev_list); /* Create debugfs entries for the opp_table */ @@ -780,6 +779,17 @@ struct opp_device *_add_opp_dev(const struct device *dev, if (ret) dev_err(dev, "%s: Failed to register opp debugfs (%d)\n", __func__, ret); + + return opp_dev; +} + +struct opp_device *_add_opp_dev(const struct device *dev, + struct opp_table *opp_table) +{ + struct opp_device *opp_dev; + + mutex_lock(&opp_table->lock); + opp_dev = _add_opp_dev_unlocked(dev, opp_table); mutex_unlock(&opp_table->lock); return opp_dev; @@ -844,6 +854,15 @@ static struct opp_table *_opp_get_opp_table(struct device *dev, int index) if (!IS_ERR(opp_table)) goto unlock; + opp_table = _managed_opp(dev, index); + if (opp_table) { + if (!_add_opp_dev_unlocked(dev, opp_table)) { + dev_pm_opp_put_opp_table(opp_table); + opp_table = NULL; + } + goto unlock; + } + opp_table = _allocate_opp_table(dev, index); unlock: diff --git a/drivers/opp/of.c b/drivers/opp/of.c index ae0436eaa911..1ddef52c27fd 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -41,11 +41,14 @@ struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node); -static struct opp_table *_managed_opp(const struct device_node *np) +struct opp_table *_managed_opp(struct device *dev, int index) { struct opp_table *opp_table, *managed_table = NULL; + struct device_node *np; - mutex_lock(&opp_table_lock); + np = _opp_of_get_opp_desc_node(dev->of_node, index); + if (!np) + return NULL; list_for_each_entry(opp_table, &opp_tables, node) { if (opp_table->np == np) { @@ -65,7 +68,7 @@ static struct opp_table *_managed_opp(const struct device_node *np) } } - mutex_unlock(&opp_table_lock); + of_node_put(np); return managed_table; } @@ -401,30 +404,19 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, { struct device_node *np; struct opp_table *opp_table; - int ret = 0, count = 0, pstate_count = 0; + int ret, count = 0, pstate_count = 0; struct dev_pm_opp *opp; - opp_table = _managed_opp(opp_np); - if (opp_table) { - /* OPPs are already managed */ - if (!_add_opp_dev(dev, opp_table)) { - ret = -ENOMEM; - goto put_opp_table; - } - - if (opp_table->parsed_static_opps) { - kref_get(&opp_table->list_kref); - return 0; - } - - goto initialize_static_opps; - } - opp_table = dev_pm_opp_get_opp_table_indexed(dev, index); if (!opp_table) return -ENOMEM; -initialize_static_opps: + /* OPP table is already initialized for the device */ + if (opp_table->parsed_static_opps) { + kref_get(&opp_table->list_kref); + return 0; + } + kref_init(&opp_table->list_kref); /* We have opp-table node now, iterate over it and add OPPs */ @@ -466,7 +458,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np, put_list_kref: _put_opp_list_kref(opp_table); -put_opp_table: dev_pm_opp_put_opp_table(opp_table); return ret; diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index f9fbb7553fc4..9c6544b4f4f9 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -206,8 +206,10 @@ 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); +struct opp_table *_managed_opp(struct device *dev, int index); #else static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {} +static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; } #endif #ifdef CONFIG_DEBUG_FS