summaryrefslogtreecommitdiff
path: root/drivers/opp/core.c
AgeCommit message (Collapse)Author
2025-01-20PM / OPP: Add reference counting helpers for Rust implementationViresh Kumar
To ensure that resources such as OPP tables or OPP nodes are not freed while in use by the Rust implementation, it is necessary to increment their reference count from Rust code. This commit introduces a new helper function, dev_pm_opp_get_opp_table_ref(), to increment the reference count of an OPP table and declares the existing helper dev_pm_opp_get() in pm_opp.h. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-12-23OPP: fix dev_pm_opp_find_bw_*() when bandwidth table not initializedNeil Armstrong
If a driver calls dev_pm_opp_find_bw_ceil/floor() the retrieve bandwidth from the OPP table but the bandwidth table was not created because the interconnect properties were missing in the OPP consumer node, the kernel will crash with: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000004 ... pc : _read_bw+0x8/0x10 lr : _opp_table_find_key+0x9c/0x174 ... Call trace: _read_bw+0x8/0x10 (P) _opp_table_find_key+0x9c/0x174 (L) _find_key+0x98/0x168 dev_pm_opp_find_bw_ceil+0x50/0x88 ... In order to fix the crash, create an assert function to check if the bandwidth table was created before trying to get a bandwidth with _read_bw(). Fixes: add1dc094a74 ("OPP: Use generic key finding helpers for bandwidth key") Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-12-23OPP: add index check to assert to avoid buffer overflow in _read_freq()Neil Armstrong
Pass the freq index to the assert function to make sure we do not read a freq out of the opp->rates[] table when called from the indexed variants: dev_pm_opp_find_freq_exact_indexed() or dev_pm_opp_find_freq_ceil/floor_indexed(). Add a secondary parameter to the assert function, unused for assert_single_clk() then add assert_clk_index() which will check for the clock index when called from the _indexed() find functions. Fixes: 142e17c1c2b4 ("OPP: Introduce dev_pm_opp_find_freq_{ceil/floor}_indexed() APIs") Fixes: a5893928bb17 ("OPP: Add dev_pm_opp_find_freq_exact_indexed()") Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-12-23opp: core: Fix off by one in dev_pm_opp_get_bw()Dan Carpenter
The "opp->bandwidth" array has "opp->opp_table->path_count" number of elements. It's allocated in _opp_allocate(). So this > needs to be >= to prevent an out of bounds access. Fixes: d78653dcd8bf ("opp: core: implement dev_pm_opp_get_bw") Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-12-23opp: core: implement dev_pm_opp_get_bwNeil Armstrong
Add and implement dev_pm_opp_get_bw() to retrieve the OPP's bandwidth in the same way as the dev_pm_opp_get_voltage() helper. Retrieving bandwidth is required in the case of the Adreno GPU where the GPU Management Unit can handle the Bandwidth scaling. The helper can get the peak or average bandwidth for any of the interconnect path. Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> [ Viresh: Fixed commit log and a comment in code ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-10-10OPP: Drop redundant *_opp_attach|detach_genpd()Ulf Hansson
All users of *_opp_attach|detach_genpd(), have been converted to use dev|devm_pm_domain_attach|detach_list(), hence let's drop it along with its corresponding exported functions. Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://lore.kernel.org/r/20241002122232.194245-12-ulf.hansson@linaro.org
2024-10-10OPP: Rework _set_required_devs() to manage a single device per callUlf Hansson
At this point there are no consumer drivers that makes use of _set_required_devs(), hence it should be straightforward to rework the code to enable it to better integrate with the PM domain attach procedure. During attach, one device at the time is being hooked up to its corresponding PM domain. Therefore, let's update the _set_required_devs() to align to this behaviour, allowing callers to fill out one required_dev per call. Subsequent changes starts making use of this. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lore.kernel.org/r/20241002122232.194245-4-ulf.hansson@linaro.org
2024-10-02OPP: fix error code in dev_pm_opp_set_config()Dan Carpenter
This is an error path so set the error code. Smatch complains about the current code: drivers/opp/core.c:2660 dev_pm_opp_set_config() error: uninitialized symbol 'ret'. Fixes: e37440e7e2c2 ("OPP: Call dev_pm_opp_set_opp() for required OPPs") Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/3f3660af-4ea0-4a89-b3b7-58de7b16d7a5@stanley.mountain Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
2024-08-23OPP: Fix support for required OPPs for multiple PM domainsUlf Hansson
It has turned out that having _set_required_opps() to recursively call dev_pm_opp_set_opp() to set the required OPPs, doesn't really work as well as we expected. More precisely, at each recursive call to dev_pm_opp_set_opp() we are changing an OPP for a required_dev that belongs to a required-OPP table. The problem with this, is that we may have several devices sharing the same required-OPP table, which leads to an incorrect behaviour in regards to aggregating the per device votes. To fix the problem for a required-OPP table belonging to a PM domain, which is the only existing usecase for now, let's simply replace the call to dev_pm_opp_set_opp() in _set_required_opps() by a call to _set_opp_level(). Moving forward we may potentially need to add support for other types of required-OPP tables. In this case, the aggregation needs to be thought of. Fixes: e37440e7e2c2 ("OPP: Call dev_pm_opp_set_opp() for required OPPs") Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lore.kernel.org/r/20240822224547.385095-2-ulf.hansson@linaro.org
2024-06-25OPP: Drop a redundant in-parameter to _set_opp_level()Ulf Hansson
The in-parameter "opp_table" isn't needed by _set_opp_level(). Let's therefore drop it. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-05-28OPP: Fix missing cleanup on error in _opp_attach_genpd()Viresh Kumar
A recent commit updated the code mistakenly to return directly on errors, without doing the required cleanups. Fix it. Fixes: 2a56c462fe5a ("OPP: Fix required_opp_tables for multiple genpds using same table") Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Closes: https://lore.kernel.org/r/202405180016.4fbn86bm-lkp@intel.com/ Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-05-17OPP: Fix required_opp_tables for multiple genpds using same tableViresh Kumar
The required_opp_tables parsing is not perfect, as the OPP core does the parsing solely based on the DT node pointers. The core sets the required_opp_tables entry to the first OPP table in the "opp_tables" list, that matches with the node pointer. If the target DT OPP table is used by multiple devices and they all create separate instances of 'struct opp_table' from it, then it is possible that the required_opp_tables entry may be set to the incorrect sibling device. Unfortunately, there is no clear way to initialize the right values during the initial parsing and we need to do this at a later point of time. Cross check the OPP table again while the genpds are attached and fix them if required. Also add a new API for the genpd core to fetch the device pointer for the genpd. Cc: Thorsten Leemhuis <regressions@leemhuis.info> Reported-by: Vladimir Lypak <vladimir.lypak@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218682 Co-developed-by: Vladimir Lypak <vladimir.lypak@gmail.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2024-03-11OPP: Extend dev_pm_opp_data with turbo supportSibi Sankar
Let's extend the dev_pm_opp_data with a turbo variable, to allow users to specify if it's a boost frequency for a dynamically added OPP. Signed-off-by: Sibi Sankar <quic_sibis@quicinc.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-01-05OPP: Rename 'rate_clk_single'Viresh Kumar
The field's name isn't clear enough. Rename it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-01-05OPP: Pass rounded rate to _set_opp()Viresh Kumar
The OPP core finds the eventual frequency to set with the help of clk_round_rate() and the same was earlier getting passed to _set_opp() and that's what would get configured. The commit 1efae8d2e777 ("OPP: Make dev_pm_opp_set_opp() independent of frequency") mistakenly changed that. Fix it. Fixes: 1efae8d2e777 ("OPP: Make dev_pm_opp_set_opp() independent of frequency") Cc: v5.18+ <stable@vger.kernel.org> # v6.0+ Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2024-01-05OPP: Relocate dev_pm_opp_sync_regulators()Viresh Kumar
Move this to a more relevant place in the file. No functional changes. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-12-28OPP: Fix _set_required_opps when opp is NULLBryan O'Donoghue
_set_required_opps can be called with opp NULL in _disable_opp_table(). commit e37440e7e2c2 ("OPP: Call dev_pm_opp_set_opp() for required OPPs") requires the opp pointer to be non-NULL to function. [ 81.253439] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048 [ 81.438407] Hardware name: Qualcomm Technologies, Inc. Robotics RB5 (DT) [ 81.445296] Workqueue: pm pm_runtime_work [ 81.449446] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 81.456609] pc : _set_required_opps+0x178/0x28c [ 81.461288] lr : _set_required_opps+0x178/0x28c [ 81.465962] sp : ffff80008078bb00 [ 81.469375] x29: ffff80008078bb00 x28: ffffd1cd71bfe308 x27: 0000000000000000 [ 81.476730] x26: ffffd1cd70ebc578 x25: ffffd1cd70a08710 x24: 00000000ffffffff [ 81.484083] x23: 00000000ffffffff x22: 0000000000000000 x21: ffff56ff892b3c48 [ 81.491435] x20: ffff56f1071c10 x19: 0000000000000000 x18: ffffffffffffffff [ 81.498788] x17: 2030207865646e69 x16: 2030303131207370 x15: 706f5f6465726975 [ 81.506141] x14: 7165725f7465735f x13: ffff5700f5c00000 x12: 00000000000008ac [ 81.513495] x11: 00000000000002e4 x10: ffff5700f6700000 x9 : ffff5700f5c00000 [ 81.520848] x8 : 00000000fffdffff x7 : ffff5700f6700000 x6 : 80000000fffe0000 [ 81.528200] x5 : ffff5700fef40d08 x4 : 0000000000000000 x3 : 0000000000000000 [ 81.535551] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff56ff81298f80 [ 81.542904] Call trace: [ 81.545437] _set_required_opps+0x178/0x28c [ 81.549754] _set_opp+0x3fc/0x5c0 [ 81.553181] dev_pm_opp_set_rate+0x90/0x26c [ 81.557498] core_power_v4+0x44/0x15c [venus_core] [ 81.562509] venus_runtime_suspend+0x40/0xd0 [venus_core] [ 81.568135] pm_generic_runtime_suspend+0x2c/0x44 [ 81.572983] __rpm_callback+0x48/0x1d8 [ 81.576852] rpm_callback+0x6c/0x78 [ 81.580453] rpm_suspend+0x10c/0x570 [ 81.584143] pm_runtime_work+0xc4/0xc8 [ 81.588011] process_one_work+0x138/0x244 [ 81.592153] worker_thread+0x320/0x438 [ 81.596021] kthread+0x110/0x114 [ 81.599355] ret_from_fork+0x10/0x20 [ 81.603052] Code: f10000ff fa5410e0 54fffbe1 97f05ae8 (f94026c5) [ 81.609317] ---[ end trace 0000000000000000 ]--- Fix it. Fixes: e37440e7e2c2 ("OPP: Call dev_pm_opp_set_opp() for required OPPs") Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> [ Viresh: Implemented the fix differently ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
2023-12-27OPP: The level field is always of unsigned int typeViresh Kumar
By mistake, dev_pm_opp_find_level_floor() used the level parameter as unsigned long instead of unsigned int. Fix it. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-28OPP: Check for invalid OPP in dev_pm_opp_find_level_ceil()Viresh Kumar
_find_key_ceil() may return an error and that must be checked before passing the same to dev_pm_opp_put(). Fixes: 41907aa4ae37 ("OPP: Level zero is valid") Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-28OPP: Don't set OPP recursively for a parent genpdViresh Kumar
Like other frameworks (clk, regulator, etc.) genpd core too takes care of propagation to performance state to parent genpds. The OPP core shouldn't attempt the same, or it may result in undefined behavior. Add checks at various places to take care of the same. Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-28OPP: Call dev_pm_opp_set_opp() for required OPPsViresh Kumar
Configuring the required OPP was never properly implemented, we just took an exception for genpds and configured them directly, while leaving out all other required OPP types. Now that a standard call to dev_pm_opp_set_opp() takes care of configuring the opp->level too, the special handling for genpds can be avoided by simply calling dev_pm_opp_set_opp() for the required OPPs, which shall eventually configure the corresponding level for genpds. This also makes it possible for us to configure other type of required OPPs (no concrete users yet though), via the same path. This is how other frameworks take care of parent nodes, like clock, regulators, etc, where we recursively call the same helper. In order to call dev_pm_opp_set_opp() for the virtual genpd devices, they must share the OPP table of the genpd. Call _add_opp_dev() for them to get that done. This commit also extends the struct dev_pm_opp_config to pass required devices, for non-genpd cases, which can be used to call dev_pm_opp_set_opp() for the non-genpd required devices. Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-28OPP: Use _set_opp_level() for single genpd caseViresh Kumar
There are two genpd (as required-opp) cases that we need to handle, devices with a single genpd and ones with multiple genpds. The multiple genpds case is clear, where the OPP core calls dev_pm_domain_attach_by_name() for them and uses the virtual devices returned by this helper to call dev_pm_domain_set_performance_state() later to change the performance state. The single genpd case however requires special handling as we need to use the same `dev` structure (instead of a virtual one provided by genpd core) for setting the performance state via dev_pm_domain_set_performance_state(). As we move towards more generic code to take care of the required OPPs, where we will recursively call dev_pm_opp_set_opp() for all the required OPPs, the above special case becomes a problem. It doesn't make sense for a device's DT entry to have both "opp-level" and single "required-opps" entry pointing to a genpd's OPP, as that would make the OPP core call dev_pm_domain_set_performance_state() for two different values for the same device structure. And so we can reuse the 'opp->level" field in such a case and call _set_opp_level() for the device. Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-28OPP: Level zero is validViresh Kumar
The level zero can be used by some OPPs to drop performance state vote for the device. It is perfectly fine to allow the same. _set_opp_level() considers it as an invalid value currently and returns early. In order to support this properly, initialize the level field with U32_MAX, which denotes unused level field. Reported-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-10-17OPP: No need to defer probe from _opp_attach_genpd()Viresh Kumar
When the new interface for attaching genpd's via the OPP core was added, it was possible for required_opp_count to be zero, but not anymore. Remove the unused check. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2023-10-17OPP: Remove genpd_virt_dev_lockViresh Kumar
All the config operations for OPP tables share common code paths now and none of the other ones have such protection in place. Either all should have it or none. The understanding here is that user won't clear the OPP configs while still using them and so such a case won't happen. We can always come back and use a wider lock for all resource types if required. Also fix the error on failing to allocate memory. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2023-10-17OPP: Reorder code in _opp_set_required_opps_genpd()Viresh Kumar
Reorder code in _opp_set_required_opps_genpd() to reduce duplicate code. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2023-10-06OPP: Remove doc style comments for internal routinesViresh Kumar
These were previously exposed outside of the OPP core and needed doc style commenting. They aren't public now and don't need the same. This fixes warnings generated for builds with `W=1`: core.c:2105: warning: Function parameter or member 'opp_table' not described in '_opp_set_supported_hw' core.c:2105: warning: Excess function parameter 'dev' description in '_opp_set_supported_hw' core.c:2148: warning: Function parameter or member 'opp_table' not described in '_opp_set_prop_name' core.c:2148: warning: Excess function parameter 'dev' description in '_opp_set_prop_name' core.c:2189: warning: Function parameter or member 'opp_table' not described in '_opp_set_regulators' core.c:2189: warning: Excess function parameter 'count' description in '_opp_set_regulators' core.c:2293: warning: Function parameter or member 'opp_table' not described in '_opp_set_clknames' core.c:2293: warning: Function parameter or member 'config_clks' not described in '_opp_set_clknames' core.c:2391: warning: Function parameter or member 'opp_table' not described in '_opp_set_config_regulators_helper' core.c:2455: warning: Function parameter or member 'opp_table' not described in '_opp_attach_genpd' core.c:2682: warning: Function parameter or member 'token' not described in 'dev_pm_opp_clear_config' core.c:2682: warning: Excess function parameter 'opp_table' description in 'dev_pm_opp_clear_config' Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202309091558.x3JJrxFI-lkp@intel.com/ Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-10-06OPP: Add dev_pm_opp_find_level_floor()Krishna chaitanya chundru
Add dev_pm_opp_find_level_floor(), as is done for frequency and bandwidth. Signed-off-by: Krishna chaitanya chundru <quic_krichai@quicinc.com> [ Viresh: Updated commit log and rearranged code ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-10-06OPP: Extend support for the opp-level beyond required-oppsUlf Hansson
At this point the level (performance state) for an OPP is currently limited to be requested for a device that is attached to a PM domain. Moreover, the device needs to have the so called required-opps assigned to it, which are based upon OPP tables being described in DT. To extend the support beyond required-opps and DT, let's enable the level to be set for all OPPs. More precisely, if the requested OPP has a valid level let's try to request it through the device's optional PM domain, via calling dev_pm_domain_set_performance_state(). Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> [ Viresh: Handle NULL opp in _set_opp_level() ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-10-06OPP: Switch to use dev_pm_domain_set_performance_state()Ulf Hansson
To support performance scaling for any kinds of PM domains, let's move away from using the genpd specific API, dev_pm_genpd_set_performance_state(), to the common dev_pm_domain_set_performance_state(). No intended functional impact at this point. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-10-06OPP: Extend dev_pm_opp_data with a levelUlf Hansson
Let's extend the dev_pm_opp_data with a level variable, to allow users to specify a corresponding level (performance state) for a dynamically added OPP. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-10-06OPP: Add dev_pm_opp_add_dynamic() to allow more flexibilityUlf Hansson
The dev_pm_opp_add() API is limited to add dynamic OPPs with a frequency and a voltage level. To enable more flexibility, let's add a new API, dev_pm_opp_add_dynamic() that's takes a struct dev_pm_opp_data* instead of a list of in-parameters. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-07-24OPP: Fix passing 0 to PTR_ERR in _opp_attach_genpd()Manivannan Sadhasivam
If dev_pm_domain_attach_by_name() returns NULL, then 0 will be passed to PTR_ERR() as reported by the smatch warning below: drivers/opp/core.c:2456 _opp_attach_genpd() warn: passing zero to 'PTR_ERR' Fix it by checking for the non-NULL virt_dev pointer before passing it to PTR_ERR. Otherwise return -ENODEV. Fixes: 4ea9496cbc95 ("opp: Fix error check in dev_pm_opp_attach_genpd()") Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-07-24OPP: Fix potential null ptr dereference in dev_pm_opp_get_required_pstate()Manivannan Sadhasivam
"opp" pointer is dereferenced before the IS_ERR_OR_NULL() check. Fix it by removing the dereference to cache opp_table and dereference it directly where opp_table is used. This fixes the following smatch warning: drivers/opp/core.c:232 dev_pm_opp_get_required_pstate() warn: variable dereferenced before IS_ERR check 'opp' (see line 230) Fixes: 84cb7ff35fcf ("OPP: pstate is only valid for genpd OPP tables") Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-07-24OPP: Reuse dev_pm_opp_get_freq_indexed()Viresh Kumar
Reuse dev_pm_opp_get_freq_indexed() from dev_pm_opp_get_freq(). Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2023-07-24OPP: Update _read_freq() to return the correct frequencyViresh Kumar
Now that we support finding indexed frequencies, lets update _read_freq() to return the right one. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
2023-07-24OPP: Add dev_pm_opp_find_freq_exact_indexed()Viresh Kumar
The indexed version of the API is added for other floor and ceil, add the same for exact as well for completeness. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-07-24OPP: Introduce dev_pm_opp_get_freq_indexed() APIManivannan Sadhasivam
In the case of devices with multiple clocks, drivers need to specify the frequency index for the OPP framework to get the specific frequency within the required OPP. So let's introduce the dev_pm_opp_get_freq_indexed() API accepting the frequency index as an argument. Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> [ Viresh: Fixed potential access to NULL opp pointer ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-07-21OPP: Introduce dev_pm_opp_find_freq_{ceil/floor}_indexed() APIsManivannan Sadhasivam
In the case of devices with multiple clocks, drivers need to specify the clock index for the OPP framework to find the OPP corresponding to the floor/ceil of the supplied frequency. So let's introduce the two new APIs accepting the clock index as an argument. These APIs use the exising _find_key_ceil() helper by supplying the clock index to it. Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> [ Viresh: Rearranged definitions in pm_opp.h ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-06-19OPP: Simplify the over-designed pstate <-> level danceViresh Kumar
While adding support for "performance states" in the OPP and genpd core, it was decided to set the `pstate` field via genpd's pm_genpd_opp_to_performance_state() helper, to allow platforms to set `pstate` even if they don't have a corresponding `level` field in the DT OPP tables (More details are present in commit 6e41766a6a50 ("PM / Domain: Implement of_genpd_opp_to_performance_state()")). Revisiting that five years later clearly suggests that it was over-designed as all current users are eventually using the `level` value only. The previous commit already added necessary checks to make sure pstate is only used for genpd tables. Lets now simplify this a little, and use `level` directly and remove `pstate` field altogether. Suggested-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2023-06-19OPP: pstate is only valid for genpd OPP tablesViresh Kumar
It is not very clear right now that the `pstate` field is only valid for genpd OPP tables and not consumer tables. And there is no checking for the same at various places. Add checks in place to verify that and make it clear to the reader. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Bjorn Andersson <quic_bjorande@quicinc.com> Tested-by: Bjorn Andersson <quic_bjorande@quicinc.com>
2023-06-14OPP: don't drop performance constraint on OPP table removalViresh Kumar
This code was added (long back) by commit 009acd196fc8 ("PM / OPP: Support updating performance state of device's power domain") and at that time the `opp->pstate` field was used to store the performance state required by a device's OPP. Over time that changed and the `->pstate` field is now used only for genpd devices and consumer devices access that via the required-opps instead. Because of all these changes, _opp_table_kref_release() now drops the constraint only when the genpd's OPP table gets freed and not the device's. Which is definitely not what we wanted. And dropping the constraint doesn't have much meaning as the genpd itself is going away. Moreover, if we want to drop constraints here, then just dropping the performance constraint alone isn't sufficient as there are other resource constraints like clk, regulator, etc. too, which must be handled. Probably the right thing to do here is to leave this decision to the consumers, which can call `dev_pm_opp_set_rate(dev, 0)` or similar APIs to drop all constraints properly. Which many of the consumers already do. Remove the special code, which is broken anyway. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2023-06-08OPP: Staticize `lazy_opp_tables` in of.cViresh Kumar
`lazy_opp_tables` is only used in of.c, move it there and mark it `static`. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-05-31opp: Fix use-after-free in lazy_opp_tables after probe deferralStephan Gerhold
When dev_pm_opp_of_find_icc_paths() in _allocate_opp_table() returns -EPROBE_DEFER, the opp_table is freed again, to wait until all the interconnect paths are available. However, if the OPP table is using required-opps then it may already have been added to the global lazy_opp_tables list. The error path does not remove the opp_table from the list again. This can cause crashes later when the provider of the required-opps is added, since we will iterate over OPP tables that have already been freed. E.g.: Unable to handle kernel NULL pointer dereference when read CPU: 0 PID: 7 Comm: kworker/0:0 Not tainted 6.4.0-rc3 PC is at _of_add_opp_table_v2 (include/linux/of.h:949 drivers/opp/of.c:98 drivers/opp/of.c:344 drivers/opp/of.c:404 drivers/opp/of.c:1032) -> lazy_link_required_opp_table() Fix this by calling _of_clear_opp_table() to remove the opp_table from the list and clear other allocated resources. While at it, also add the missing mutex_destroy() calls in the error path. Cc: stable@vger.kernel.org Suggested-by: Viresh Kumar <viresh.kumar@linaro.org> Fixes: 7eba0c7641b0 ("opp: Allow lazy-linking of required-opps") Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-05-22OPP: rate-limit debug messages when no change in OPP is requiredAdrián Larumbe
Otherwise, when enabling a debug build and dynamic debug in the kernel, it quickly floods the kernel ring buffer and makes debugging of other subsystems almost impossible, unless manually disabled. Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-04-03OPP: Move required opps configuration to specialized callbackViresh Kumar
The required-opps configuration is closely tied to genpd and performance states at the moment and it is not very obvious that required-opps can live without genpds. Though we don't support configuring required-opps for non-genpd cases currently. This commit aims at separating these parts, where configuring genpds would be a special case of configuring the required-opps. Add a specialized callback, set_required_opps(), to the opp table and set it to different callbacks accordingly. This shouldn't result in any functional changes for now. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2023-04-03OPP: Handle all genpd cases together in _set_required_opps()Viresh Kumar
There is no real need of keeping separate code for single genpd case, it can be made to work with a simple change. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
2022-08-16OPP: Fix an un-initialized variable usageChristophe JAILLET
smatch complains that 'ret' may be returned un-initialized. Explicitly return 0 if we reach the end of the function (should 'opp_table->clk_count' be 0). Fixes: 8174a3a613af ("OPP: Provide a simple implementation to configure multiple clocks") Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2022-07-19OPP: Don't drop opp->np reference while it is still in useLiang He
The struct dev_pm_opp contains a reference of the DT node, opp->np, throughout its lifetime. We should increase the refcount for the same from _opp_add_static_v2(), and drop it while removing the OPP finally. Signed-off-by: Liang He <windhl@126.com> [ Viresh: Updated subject / commit log, create _of_clear_opp() and drop reference from it] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2022-07-12OPP: Allow config_clks helper for single clk caseViresh Kumar
There is a corner case with Tegra30, where we want to skip clk configuration via dev_pm_opp_set_opp(), but still want the OPP core to read the "opp-hz" property so we can find the right OPP via freq finding helpers. This is the easiest of the ways to make it work, without any special hacks in the OPP core. Allow config_clks to be passed for single clk case. Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>