From patchwork Mon Apr 9 11:43:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 133027 Delivered-To: patch@linaro.org Received: by 10.46.84.29 with SMTP id i29csp168173ljb; Mon, 9 Apr 2018 04:44:21 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/q2BbjudgjwbTouPplEyGr4Ym5L21Tq1pHo2yqN4dw9Rg6LrwUVZEarAKdTmsOtZzaPrbX X-Received: by 2002:a17:902:341:: with SMTP id 59-v6mr37250158pld.407.1523274261365; Mon, 09 Apr 2018 04:44:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523274261; cv=none; d=google.com; s=arc-20160816; b=pTGJgi+1ToE2udeKG8ALuJh110xafNRgBbxzs3MQHwSV1ICtk2NM6O4auKTDaQgYKF ujcEgio7WGD7P4um2wExOM0gvPH81fRl/gfLmiCBtO8UMfELIDxyd7azsuzURIboKPKo 4dPEt8sNhf7aSsX3w2K7Ymre3Mgb9CV5NDpLuIKlglV6CmtkQ2ziXDeTmcJVWCBbmRJ4 g8FJc8Ed48nskPBg2SfS7GuQF9DCiymyiXG3WPJZw8zufXzX+NLivEwiwQmuopA/3AZz yAGY22o3tlwpWPM3xOx+cfvvA5mzGP12ofIfQuxMIrdbJGacCHR8BIXZKUcfS7/hAFNG xGjw== 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 :arc-authentication-results; bh=FbTClrwyMcmHg+co92jGj7lk/HteBOT5VmTDz5/SBlk=; b=dLfxJSDx7sS3yNcRor0Wh5AkRswjRmtXvWmGTEThqQWT6zEsvGqJvNuTc1gp1m2Uxt +Go5v69UVzS8PkpmevLrQGQCmvlygQaISRB2XLDBlAPcc7aG82hlwLUS5BHYXUp5UaA3 0ToWU7xsdf9NNfqdyFxxWZMKwF3rly6KIN3ZKROlLdVR6cAGAsqFz6Y5TNI3YWomWz9D nxNskGEn1hO/rqNxp6qn7eO89/BZu9aEZb6yjjLF1MH/tdkv3lFZ9pPtWYhPCrfOoFtr ZDUo4OZeEZ3iz9uCzdAz1llEieI/D+9Dasy5R0G+eJNAlHNDnDNrbUydiHl+EKxMNChy S3vg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=M/LHhsl2; 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 j188si105815pgc.584.2018.04.09.04.44.21; Mon, 09 Apr 2018 04:44:21 -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=M/LHhsl2; 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 S1751736AbeDILoU (ORCPT + 11 others); Mon, 9 Apr 2018 07:44:20 -0400 Received: from mail-pl0-f65.google.com ([209.85.160.65]:45526 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751589AbeDILoT (ORCPT ); Mon, 9 Apr 2018 07:44:19 -0400 Received: by mail-pl0-f65.google.com with SMTP id e22-v6so3200349plj.12 for ; Mon, 09 Apr 2018 04:44:19 -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=FbTClrwyMcmHg+co92jGj7lk/HteBOT5VmTDz5/SBlk=; b=M/LHhsl2sjWJNn4cpGJ1iwmyDiilpry2b6zWCGv8cxW2V9QdkWt8rBaxOteLbEn7x/ LUhnnYR1ZZaaiJ9/4C4z1gZDnspp9cDiuy1rji0NezgDU2RfvwDF6mNk7NWuxp+2wx4g /iD/LAdyQ7Z2k1fIkRpxW7OOo3cTDxoZ+Zk68= 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=FbTClrwyMcmHg+co92jGj7lk/HteBOT5VmTDz5/SBlk=; b=akEd95sR4Y06/fee82DdLk9Krxp+tiKLRRIsGDRsUpUGAGdhtjlZ3P/QwODmuI7mCV CPbGA9U37mFyYLucPbSsSfeGppbXJehifnxAEVF6S9qZlRjDuMvoidUP/9lEWntY60J5 oCS7SspjjyemZv87iqwnXa3XV/2x1ksHDo8uBe8HmDIjuw6ncKrNsMfa2d1xwuoC7rrI 51QQ9v81yKKxUae6S5aDjoHALsmty65UNuN6n56BatEX/nRpJ6uqxzSq1UNeFeVqUnpQ HSAB5lgWVzbvaY5amUTbzBSqEf9FM2XH7OnwyJBAgr11KDWDhGlfkaWqt6ZDr4U8/dO7 GhNQ== X-Gm-Message-State: AElRT7Ftn5njJF58wzJlZ+CgMLceNkkUfmEQ4CpxzORiUyfqbEadz+0r izBF4BnUgvYqDVzwXnwVWq2veA== X-Received: by 2002:a17:902:7087:: with SMTP id z7-v6mr39162538plk.315.1523274259137; Mon, 09 Apr 2018 04:44:19 -0700 (PDT) Received: from localhost ([122.171.228.188]) by smtp.gmail.com with ESMTPSA id o18sm433927pgd.59.2018.04.09.04.44.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Apr 2018 04:44:18 -0700 (PDT) From: Viresh Kumar To: Ulf Hansson , Stephen Boyd , Viresh Kumar , Nishanth Menon Cc: Viresh Kumar , Rajendra Nayak , Vincent Guittot , linux-pm@vger.kernel.org Subject: [PATCH V2 03/11] PM / OPP: "opp-hz" is optional for power domains Date: Mon, 9 Apr 2018 17:13:43 +0530 Message-Id: X-Mailer: git-send-email 2.15.0.194.g9af6a3dea062 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 "opp-hz" property is optional for power domains, don't error out if it is missing. Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 92 +++++++++++++++++++++++++++++++-------------------- drivers/opp/debugfs.c | 15 +++++++-- drivers/opp/of.c | 26 ++++++++++----- drivers/opp/opp.h | 3 +- 4 files changed, 89 insertions(+), 47 deletions(-) -- 2.15.0.194.g9af6a3dea062 Reviewed-by: Ulf Hansson diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 92fa94a6dcc1..a0f72c732718 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -281,6 +281,23 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq); +int _get_opp_count(struct opp_table *opp_table) +{ + struct dev_pm_opp *opp; + int count = 0; + + mutex_lock(&opp_table->lock); + + list_for_each_entry(opp, &opp_table->opp_list, node) { + if (opp->available) + count++; + } + + mutex_unlock(&opp_table->lock); + + return count; +} + /** * dev_pm_opp_get_opp_count() - Get number of opps available in the opp table * @dev: device for which we do this operation @@ -291,25 +308,17 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq); int dev_pm_opp_get_opp_count(struct device *dev) { struct opp_table *opp_table; - struct dev_pm_opp *temp_opp; - int count = 0; + int count; opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { count = PTR_ERR(opp_table); dev_dbg(dev, "%s: OPP table not found (%d)\n", __func__, count); - return count; - } - - mutex_lock(&opp_table->lock); - - list_for_each_entry(temp_opp, &opp_table->opp_list, node) { - if (temp_opp->available) - count++; + return 0; } - mutex_unlock(&opp_table->lock); + count = _get_opp_count(opp_table); dev_pm_opp_put_opp_table(opp_table); return count; @@ -985,22 +994,11 @@ static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, return true; } -/* - * Returns: - * 0: On success. And appropriate error message for duplicate OPPs. - * -EBUSY: For OPP with same freq/volt and is available. The callers of - * _opp_add() must return 0 if they receive -EBUSY from it. This is to make - * sure we don't print error messages unnecessarily if different parts of - * kernel try to initialize the OPP table. - * -EEXIST: For OPP with same freq but different volt or is unavailable. This - * should be considered an error by the callers of _opp_add(). - */ -int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, - struct opp_table *opp_table) +static int _opp_is_duplicate(struct device *dev, struct dev_pm_opp *new_opp, + struct opp_table *opp_table, + struct list_head **head) { struct dev_pm_opp *opp; - struct list_head *head; - int ret; /* * Insert new OPP in order of increasing frequency and discard if @@ -1010,17 +1008,14 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, * loop, don't replace it with head otherwise it will become an infinite * loop. */ - mutex_lock(&opp_table->lock); - head = &opp_table->opp_list; - list_for_each_entry(opp, &opp_table->opp_list, node) { if (new_opp->rate > opp->rate) { - head = &opp->node; + *head = &opp->node; continue; } if (new_opp->rate < opp->rate) - break; + return 0; /* Duplicate OPPs */ dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n", @@ -1029,11 +1024,38 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, new_opp->supplies[0].u_volt, new_opp->available); /* Should we compare voltages for all regulators here ? */ - ret = opp->available && - new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? -EBUSY : -EEXIST; + return opp->available && + new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? -EBUSY : -EEXIST; + } + + return 0; +} + +/* + * Returns: + * 0: On success. And appropriate error message for duplicate OPPs. + * -EBUSY: For OPP with same freq/volt and is available. The callers of + * _opp_add() must return 0 if they receive -EBUSY from it. This is to make + * sure we don't print error messages unnecessarily if different parts of + * kernel try to initialize the OPP table. + * -EEXIST: For OPP with same freq but different volt or is unavailable. This + * should be considered an error by the callers of _opp_add(). + */ +int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, + struct opp_table *opp_table, bool rate_not_available) +{ + struct list_head *head; + int ret; + + mutex_lock(&opp_table->lock); + head = &opp_table->opp_list; - mutex_unlock(&opp_table->lock); - return ret; + if (likely(!rate_not_available)) { + ret = _opp_is_duplicate(dev, new_opp, opp_table, &head); + if (ret) { + mutex_unlock(&opp_table->lock); + return ret; + } } if (opp_table->get_pstate) @@ -1104,7 +1126,7 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev, new_opp->available = true; new_opp->dynamic = dynamic; - ret = _opp_add(dev, new_opp, opp_table); + ret = _opp_add(dev, new_opp, opp_table, false); if (ret) { /* Don't return error for duplicate OPPs */ if (ret == -EBUSY) diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c index b03c03576a62..e6828e5f81b0 100644 --- a/drivers/opp/debugfs.c +++ b/drivers/opp/debugfs.c @@ -77,10 +77,21 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) { struct dentry *pdentry = opp_table->dentry; struct dentry *d; + unsigned long id; char name[25]; /* 20 chars for 64 bit value + 5 (opp:\0) */ - /* Rate is unique to each OPP, use it to give opp-name */ - snprintf(name, sizeof(name), "opp:%lu", opp->rate); + /* + * Get directory name for OPP. + * + * - Normally rate is unique to each OPP, use it to get unique opp-name. + * - For some devices rate isn't available, use index instead. + */ + if (likely(opp->rate)) + id = opp->rate; + else + id = _get_opp_count(opp_table); + + snprintf(name, sizeof(name), "opp:%lu", id); /* Create per-opp directory */ d = debugfs_create_dir(name, pdentry); diff --git a/drivers/opp/of.c b/drivers/opp/of.c index cb716aa2f44b..c5c5afcaa2e3 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -292,6 +292,7 @@ static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev, u64 rate; u32 val; int ret; + bool rate_not_available = false; new_opp = _opp_allocate(opp_table); if (!new_opp) @@ -299,8 +300,21 @@ static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev, ret = of_property_read_u64(np, "opp-hz", &rate); if (ret < 0) { - dev_err(dev, "%s: opp-hz not found\n", __func__); - goto free_opp; + /* "opp-hz" is optional for devices like power domains. */ + if (!of_find_property(dev->of_node, "#power-domain-cells", + NULL)) { + dev_err(dev, "%s: opp-hz not found\n", __func__); + goto free_opp; + } + + rate_not_available = true; + } else { + /* + * Rate is defined as an unsigned long in clk API, and so + * casting explicitly to its type. Must be fixed once rate is 64 + * bit guaranteed in clk API. + */ + new_opp->rate = (unsigned long)rate; } /* Check if the OPP supports hardware's hierarchy of versions or not */ @@ -309,12 +323,6 @@ static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev, goto free_opp; } - /* - * Rate is defined as an unsigned long in clk API, and so casting - * explicitly to its type. Must be fixed once rate is 64 bit - * guaranteed in clk API. - */ - new_opp->rate = (unsigned long)rate; new_opp->turbo = of_property_read_bool(np, "turbo-mode"); new_opp->np = np; @@ -328,7 +336,7 @@ static int _opp_add_static_v2(struct opp_table *opp_table, struct device *dev, if (ret) goto free_opp; - ret = _opp_add(dev, new_opp, opp_table); + ret = _opp_add(dev, new_opp, opp_table, rate_not_available); if (ret) { /* Don't return error for duplicate OPPs */ if (ret == -EBUSY) diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 4d00061648a3..381a4fb15d5c 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -188,13 +188,14 @@ struct opp_table { /* Routines internal to opp core */ 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, bool remove_all); void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all); struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table); void _opp_free(struct dev_pm_opp *opp); -int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table); +int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available); 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);