aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/opp/of.c (follow)
AgeCommit message (Collapse)AuthorFilesLines
2018-10-04PM / OPP: _of_add_opp_table_v2(): increment count only if OPP is addedDave Gerlach1-13/+20
Currently the _of_add_opp_table_v2 call loops through the OPP nodes in the operating-points-v2 table in the device tree and calls _opp_add_static_v2 for each to add them to the table. It counts each iteration through this loop as an added OPP, however there are cases where _opp_add_static_v2() returns 0 but no new OPP is added to the list. This can happen while adding duplicate OPP or if the OPP isn't supported by hardware. Because of this the count variable will contain the number of OPP nodes in the table in device tree but not necessarily the ones that are actually added. As this count value is what is checked to determine if there are any valid OPPs, if a platform has an operating-points-v2 table with all OPP nodes containing opp-supported-hw values that are not currently supported, then _of_add_opp_table_v2 will fail to abort as it should due to an empty table. Additionally, since commit 3ba98324e81a ("PM / OPP: Get performance state using genpd helper"), the same count variable is compared against the number of OPPs containing performance states and requires that either all or none have pstates set, however in the case of any opp table that has any entries that do not get added by _opp_add_static_v2 due to incompatible opp-supported-hw fields, these numbers will not match and _of_add_opp_table_v2 will incorrectly fail. We need to clearly identify all the three cases (success, failure, unsupported/duplicate OPPs) and then increment count only on success case. Change return type of _opp_add_static_v2() to return the pointer to the newly added OPP instead of an integer. This routine now returns a valid pointer if the OPP is really added, NULL for unsupported or duplicate OPPs, and error value cased as a pointer on errors. Ideally the fixes tag in this commit should point back to the commit that introduced OPP v2 initially, as that's where we started incorrectly accounting for duplicate OPPs: commit 274659029c9d ("PM / OPP: Add support to parse "operating-points-v2" bindings") But it wasn't a real problem until recently as the count was only used to check if any OPPs are added or not. And so this commit points to a rather recent commit where we added more code that depends on the value of "count". Fixes: 3ba98324e81a ("PM / OPP: Get performance state using genpd helper") Reported-by: Dave Gerlach <d-gerlach@ti.com> Reported-by: Niklas Cassel <niklas.cassel@linaro.org> Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Dave Gerlach <d-gerlach@ti.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-10-04OPP: Improve error handling in dev_pm_opp_of_cpumask_add_table()Viresh Kumar1-6/+12
The error handling wasn't appropriate in dev_pm_opp_of_cpumask_add_table(). For example it returns 0 on success and also for the case where cpumask is empty or cpu_device wasn't found for any of the CPUs. It should really return error on such cases, so that the callers can be aware of the outcome. Fix it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-10-01OPP: Pass OPP table to _of_add_opp_table_v{1|2}()Viresh Kumar1-40/+28
Both _of_add_opp_table_v1() and _of_add_opp_table_v2() contain similar code to get the OPP table and their parent routine also parses the DT to find the OPP table's node pointer. This can be simplified by getting the OPP table in advance and then passing it as argument to these routines. Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-10-01OPP: Prevent creating multiple OPP tables for devices sharing OPP nodesViresh Kumar1-22/+13
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 <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Use a single mechanism to free the OPP tableViresh Kumar1-14/+18
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. Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Don't remove dynamic OPPs from _dev_pm_opp_remove_table()Viresh Kumar1-6/+6
Only one platform was depending on this feature and it is already updated now. Stop removing dynamic OPPs from _dev_pm_opp_remove_table(). This simplifies lot of paths and removes unnecessary parameters. Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Create separate kref for static OPPs listViresh Kumar1-0/+7
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 <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Parse OPP table's DT properties from _of_init_opp_table()Viresh Kumar1-31/+48
Parse the DT properties present in the OPP table from _of_init_opp_table(), which is a dedicated routine for DT parsing. Minor relocation of helpers is required for this. It is possible now for _managed_opp() to return a partially initialized OPP table if the OPP table is created via the helpers like dev_pm_opp_set_supported_hw() and we need another flag to indicate if the static OPP are already parsed or not to make sure we don't incorrectly skip initializing the static OPPs. Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Pass index to _of_init_opp_table()Viresh Kumar1-5/+7
This is a preparatory patch required for the next commit which will start using OPP table's node pointer in _of_init_opp_table(), which requires the index in order to read the OPP table's phandle. This commit adds the index argument in the call chains in order to get it delivered to _of_init_opp_table(). Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Don't try to remove all OPP tables on failureViresh Kumar1-2/+2
dev_pm_opp_of_cpumask_add_table() creates the OPP table for all CPUs present in the cpumask and on errors it should revert all changes it has done. It actually is doing a bit more than that. On errors, it tries to free all the OPP tables, even the one it hasn't created yet. This may also end up freeing the OPP tables which were created from separate path, like dev_pm_opp_set_supported_hw(). Reported-and-tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-09-19OPP: Free OPP table properly on performance state irregularitiesViresh Kumar1-0/+1
The OPP table was freed, but not the individual OPPs which is done from _dev_pm_opp_remove_table(). Fix it by calling _dev_pm_opp_remove_table() as well. Cc: 4.18 <stable@vger.kernel.org> # v4.18 Fixes: 3ba98324e81a ("PM / OPP: Get performance state using genpd helper") Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-05-30OPP: Allow same OPP table to be used for multiple genpdViresh Kumar1-2/+15
The OPP binding says: Property: operating-points-v2 ... This can contain more than one phandle for power domain providers that provide multiple power domains. That is, one phandle for each power domain. If only one phandle is available, then the same OPP table will be used for all power domains provided by the power domain provider. But the OPP core isn't allowing the same OPP table to be used for multiple domains. Update dev_pm_opp_of_add_table_indexed() to allow that. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Rajendra Nayak <rnayak@codeaurora.org>
2018-05-16PM / OPP: silence an uninitialized variable warningDan Carpenter1-1/+1
Smatch complains that it's possible we print "rate" in the debug output when it hasn't been initialized. It should be zero on that path. Fixes: a1e8c13600bf ("PM / OPP: "opp-hz" is optional for power domains") [ Viresh: Added the Fixes tag ] Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2018-05-09PM / OPP: Get performance state using genpd helperViresh Kumar1-1/+19
The genpd core provides an API now to retrieve the performance state from DT, use that instead of the ->get_pstate() callback. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-05-09PM / OPP: Implement dev_pm_opp_get_of_node()Viresh Kumar1-0/+19
This adds a new helper to let the power domain drivers to access opp->np, so that they can read platform specific properties from the node. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-05-09PM / OPP: Implement of_dev_pm_opp_find_required_opp()Viresh Kumar1-0/+54
A device's DT node or its OPP nodes can contain a phandle to other device's OPP node, in the "required-opps" property. This patch implements a routine to find that required OPP from the node that contains the "required-opps" property. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-05-09PM / OPP: Implement dev_pm_opp_of_add_table_indexed()Viresh Kumar1-9/+41
The "operating-points-v2" property can contain a list of phandles now, specifically for the power domain providers that provide multiple domains. Add support to parse that. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2018-05-09PM / OPP: "opp-hz" is optional for power domainsViresh Kumar1-9/+17
"opp-hz" property is optional for power domains now and we shouldn't error out if it is missing for power domains. This patch creates two new routines, _get_opp_count() and _opp_is_duplicate(), by separating existing code from their parent functions. Also skip duplicate OPP check for power domain OPPs as they may not have any the "opp-hz" field, but a platform specific performance state binding to uniquely identify OPP nodes. By default the debugfs OPP nodes are named using the "rate" value, but that isn't possible for the power domain OPP nodes and hence they use the index of the OPP node in the OPP node list instead. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2017-10-14PM / OPP: add missing of_node_put() for of_get_cpu_node()Sudeep Holla1-2/+3
Commit 762792913f8c (PM / OPP: Fix get sharing CPUs when hotplug is used) moved away from using cpu_dev->of_node because of some limitations. However, commit 7467c9d95989 (of: return of_get_cpu_node from of_cpu_device_node_get if CPUs are not registered) added support to fall back to of_get_cpu_node() if called if CPUs are not registered yet. Add the missing of_node_put() for the CPU device nodes. Also go back to using of_cpu_device_node_get() in dev_pm_opp_of_get_sharing_cpus() to avoid scanning the device tree again. Acked-by: Viresh Kumar <vireshk@kernel.org> Fixes: 762792913f8c (PM / OPP: Fix get sharing CPUs when hotplug is used) Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-10-11PM / OPP: Add missing of_node_put(np)Tobias Jordan1-0/+1
The for_each_available_child_of_node() loop in _of_add_opp_table_v2() doesn't drop the reference to "np" on errors. Fix that. Fixes: 274659029c9d (PM / OPP: Add support to parse "operating-points-v2" bindings) Cc: 4.3+ <stable@vger.kernel.org> # 4.3+ Signed-off-by: Tobias Jordan <Tobias.Jordan@elektrobit.com> [ VK: Improved commit log. ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-10-03PM / OPP: Move the OPP directory out of power/Viresh Kumar1-0/+633
The drivers/base/power/ directory is special and contains code related to power management core like system suspend/resume, hibernation, etc. It was fine to keep the OPP code inside it when we had just one file for it, but it is growing now and already has a directory for itself. Lets move it directly under drivers/ directory, just like cpufreq and cpuidle. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>