From patchwork Thu Nov 19 02:00:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 56960 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp2904413lbb; Wed, 18 Nov 2015 18:00:35 -0800 (PST) X-Received: by 10.68.57.208 with SMTP id k16mr6780032pbq.70.1447898434887; Wed, 18 Nov 2015 18:00:34 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id cn3si8140494pad.43.2015.11.18.18.00.34; Wed, 18 Nov 2015 18:00:34 -0800 (PST) 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; 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; dkim=neutral (body hash did not verify) header.i=@linaro-org.20150623.gappssmtp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756547AbbKSCAb (ORCPT + 28 others); Wed, 18 Nov 2015 21:00:31 -0500 Received: from mail-pa0-f44.google.com ([209.85.220.44]:36553 "EHLO mail-pa0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752191AbbKSCA3 (ORCPT ); Wed, 18 Nov 2015 21:00:29 -0500 Received: by pacdm15 with SMTP id dm15so63467726pac.3 for ; Wed, 18 Nov 2015 18:00:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro-org.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=uQFZwQcaue1OS/MtsscVHebQPyXvgncfz5qBQ4OlqiQ=; b=EwQvC6r/1ckjYSVgRRoFenAqWZ/TzT9DEBxVJbGcrJW1l2Dwy167cxYI/2pfHdq6vM lrkGchj5saeW/FRLCHAUFKMM0itkQP8zMe6P1YZgdyP3TrayD/tsQBrc10DvSiTKHzlv SckemZaicIiKl2zrStrYsZzjnlUPJXMZgyLgezBSSKewfD3Dxpl/SziCRaH/Jb3bh8PR N9COJj8DG0BcRP/MmBYrivkwQBX3Qc2zPdfOiC1Qb1sKdWs09YeaPqaH0Hf2UW59fPKP 5e9t+8tNEymkDm+DPlN35I9impTqbDmfJqeXVpo0PBl+xToCpLs551PQS05TBLzbwRwf X3UQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-type:content-disposition:in-reply-to :user-agent; bh=uQFZwQcaue1OS/MtsscVHebQPyXvgncfz5qBQ4OlqiQ=; b=dnpATC3Kw43tSGz3Nu6djpMrrTdH8cYNxTH9phzry80XGdWd5u0Eb73yUB4hjrPlC7 mTy++NCpxF5XI4UhG7oi2uUCuCwEWqoDsfkUeKZX7JfO8Q4nE6ykkp7P/hMEKpiNwB0W hvAvgxWMLeM8rRTP1P0xQ/uSdEC6k93pSvK88CCUUxpN1jjevaW2oFoLA7GM5z9j1qem kWEpcYc1qCcStZF74w0IM+KN5i9UUlwbx1gzw6N8U1AVoGboRmhm9VPqx/06dpaI17A8 Txzf7lJUjV1sQLsJD7/zGQqBAY8nnwRKuyplxcKUM26PZ+Me0g/4+NukC4+gplA1FLWs FRvA== X-Gm-Message-State: ALoCoQlIPgm7wq+gKy72J6ACWGRuTGMGKOdG49fdLsQt6qUDdOSSbja77B7STqfqOfTWUS0XtMzT X-Received: by 10.68.234.166 with SMTP id uf6mr6757459pbc.126.1447898428531; Wed, 18 Nov 2015 18:00:28 -0800 (PST) Received: from localhost ([122.167.29.19]) by smtp.gmail.com with ESMTPSA id v17sm6616130pbs.69.2015.11.18.18.00.26 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 18 Nov 2015 18:00:27 -0800 (PST) Date: Thu, 19 Nov 2015 07:30:23 +0530 From: Viresh Kumar To: Stephen Boyd Cc: Rafael Wysocki , linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, robh+dt@kernel.org, nm@ti.com, Bartlomiej Zolnierkiewicz , Dmitry Torokhov , Greg Kroah-Hartman , Len Brown , open list , Pavel Machek , Shawn Guo Subject: Re: [PATCH 2/3] PM / OPP: Parse 'opp-supported-hw' binding Message-ID: <20151119020023.GL7336@ubuntu> References: <6d603a73028b40493b280ba7ac9c3fcb51bb2362.1447669859.git.viresh.kumar@linaro.org> <20151118225358.GJ32672@codeaurora.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20151118225358.GJ32672@codeaurora.org> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 18-11-15, 14:53, Stephen Boyd wrote: > Why do we need to allocate an array to check the property a u32 > at a time? We should be able to call of_property_read_u32_index() > in a loop and check that against the version array. No allocation > needed. -------------------------8<------------------------- From: Viresh Kumar Date: Tue, 15 Sep 2015 12:53:00 +0530 Subject: [PATCH] PM / OPP: Parse 'opp-supported-hw' binding OPP bindings allow a platform to enable OPPs based on the version of the hardware they are used for. Add support to the OPP-core to parse these bindings, by introducing dev_pm_opp_{set|put}_supported_hw() APIs. Signed-off-by: Viresh Kumar --- drivers/base/power/opp/core.c | 124 ++++++++++++++++++++++++++++++++++++++++++ drivers/base/power/opp/opp.h | 5 ++ include/linux/pm_opp.h | 13 +++++ 3 files changed, 142 insertions(+) -- viresh -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 6aa172be6e8e..93f7b8c87a26 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -559,6 +559,9 @@ static void _remove_device_opp(struct device_opp *dev_opp) if (!list_empty(&dev_opp->opp_list)) return; + if (dev_opp->supported_hw) + return; + list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp, node); @@ -834,6 +837,121 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev) } /** + * dev_pm_opp_set_supported_hw() - Set supported platforms + * @dev: Device for which supported-hw has to be set. + * @versions: Array of hierarchy of versions to match. + * @count: Number of elements in the array. + * + * This is required only for the V2 bindings, and it enables a platform to + * specify the hierarchy of versions it supports. OPP layer will then enable + * OPPs, which are available for those versions, based on its 'opp-supported-hw' + * property. + */ +int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, + unsigned int count) +{ + struct device_opp *dev_opp; + int ret = 0; + + /* Operations on OPP structures must be done from within rcu locks */ + rcu_read_lock(); + + dev_opp = _add_device_opp(dev); + if (!dev_opp) + return -ENOMEM; + + /* Do we already have a version hierarchy associated with dev_opp? */ + if (dev_opp->supported_hw) { + dev_err(dev, "%s: Already have supported hardware list\n", + __func__); + ret = -EBUSY; + goto unlock; + } + + dev_opp->supported_hw = kmemdup(versions, count * sizeof(*versions), + GFP_KERNEL); + if (!dev_opp->supported_hw) { + ret = -ENOMEM; + goto unlock; + } + + dev_opp->supported_hw_count = count; + +unlock: + rcu_read_unlock(); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw); + +/** + * dev_pm_opp_put_supported_hw() - Releases resources blocked for supported hw + * @dev: Device for which supported-hw has to be set. + * + * This is required only for the V2 bindings, and is called for a matching + * dev_pm_opp_set_supported_hw(). Until this is called, the device_opp structure + * will not be freed. + */ +void dev_pm_opp_put_supported_hw(struct device *dev) +{ + struct device_opp *dev_opp; + + /* Operations on OPP structures must be done from within rcu locks */ + rcu_read_lock(); + + /* Check for existing list for 'dev' first */ + dev_opp = _find_device_opp(dev); + if (IS_ERR(dev_opp)) { + dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp)); + goto unlock; + } + + if (!dev_opp->supported_hw) { + dev_err(dev, "%s: Doesn't have supported hardware list\n", + __func__); + goto unlock; + } + + kfree(dev_opp->supported_hw); + dev_opp->supported_hw = NULL; + dev_opp->supported_hw_count = 0; + + /* Try freeing device_opp if this was the last blocking resource */ + _remove_device_opp(dev_opp); + +unlock: + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw); + +static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp, + struct device_node *np) +{ + unsigned int count = dev_opp->supported_hw_count; + u32 version; + int ret; + + if (!dev_opp->supported_hw) + return true; + + while (count--) { + ret = of_property_read_u32_index(np, "opp-supported-hw", count, + &version); + if (ret) { + dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n", + __func__, count, ret); + return false; + } + + /* Both of these are bitwise masks of the versions */ + if (!(version & dev_opp->supported_hw[count])) + return false; + } + + return true; +} + +/** * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings) * @dev: device for which we do this operation * @np: device node @@ -879,6 +997,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np) goto free_opp; } + /* Check if the OPP supports hardware's hierarchy of versions or not */ + if (!_opp_is_supported(dev, dev_opp, np)) { + dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate); + 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 diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index b8880c7f8be1..70f4564a6ab9 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -129,6 +129,8 @@ struct device_list_opp { * @clock_latency_ns_max: Max clock latency in nanoseconds. * @shared_opp: OPP is shared between multiple devices. * @suspend_opp: Pointer to OPP to be used during device suspend. + * @supported_hw: Array of version number to support. + * @supported_hw_count: Number of elements in supported_hw array. * @dentry: debugfs dentry pointer of the real device directory (not links). * @dentry_name: Name of the real dentry. * @@ -153,6 +155,9 @@ struct device_opp { bool shared_opp; struct dev_pm_opp *suspend_opp; + unsigned int *supported_hw; + unsigned int supported_hw_count; + #ifdef CONFIG_DEBUG_FS struct dentry *dentry; char dentry_name[NAME_MAX]; diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 9a2e50337af9..3a85110242f0 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -55,6 +55,9 @@ int dev_pm_opp_enable(struct device *dev, unsigned long freq); int dev_pm_opp_disable(struct device *dev, unsigned long freq); struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev); +int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, + unsigned int count); +void dev_pm_opp_put_supported_hw(struct device *dev); #else static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) { @@ -129,6 +132,16 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( { return ERR_PTR(-EINVAL); } + +static inline int dev_pm_opp_set_supported_hw(struct device *dev, + const u32 *versions, + unsigned int count) +{ + return -EINVAL; +} + +static inline void dev_pm_opp_put_supported_hw(struct device *dev) {} + #endif /* CONFIG_PM_OPP */ #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)