Loading drivers/opp/core.c +79 −155 Original line number Diff line number Diff line Loading @@ -317,18 +317,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo); */ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) { struct opp_table *opp_table; unsigned long clock_latency_ns; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return 0; clock_latency_ns = opp_table->clock_latency_ns_max; dev_pm_opp_put_opp_table(opp_table); return clock_latency_ns; return opp_table->clock_latency_ns_max; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); Loading @@ -340,7 +335,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); */ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); struct dev_pm_opp *opp; struct regulator *reg; unsigned long latency_ns = 0; Loading @@ -356,13 +351,13 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) /* Regulator may not be required for the device */ if (!opp_table->regulators) goto put_opp_table; return 0; count = opp_table->regulator_count; uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL); if (!uV) goto put_opp_table; return 0; mutex_lock(&opp_table->lock); Loading Loading @@ -395,8 +390,6 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) } kfree(uV); put_opp_table: dev_pm_opp_put_opp_table(opp_table); return latency_ns; } Loading Loading @@ -426,7 +419,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_transition_latency); */ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); unsigned long freq = 0; opp_table = _find_opp_table(dev); Loading @@ -436,8 +429,6 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) if (opp_table->suspend_opp && opp_table->suspend_opp->available) freq = dev_pm_opp_get_freq(opp_table->suspend_opp); dev_pm_opp_put_opp_table(opp_table); return freq; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq); Loading Loading @@ -468,21 +459,16 @@ int _get_opp_count(struct opp_table *opp_table) */ int dev_pm_opp_get_opp_count(struct device *dev) { struct opp_table *opp_table; int count; struct opp_table *opp_table __free(put_opp_table); 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; dev_dbg(dev, "%s: OPP table not found (%ld)\n", __func__, PTR_ERR(opp_table)); return PTR_ERR(opp_table); } count = _get_opp_count(opp_table); dev_pm_opp_put_opp_table(opp_table); return count; return _get_opp_count(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); Loading Loading @@ -576,8 +562,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available, unsigned long opp_key, unsigned long key), bool (*assert)(struct opp_table *opp_table, unsigned int index)) { struct opp_table *opp_table; struct dev_pm_opp *opp; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { Loading @@ -586,12 +571,8 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available, return ERR_CAST(opp_table); } opp = _opp_table_find_key(opp_table, key, index, available, read, return _opp_table_find_key(opp_table, key, index, available, read, compare, assert); dev_pm_opp_put_opp_table(opp_table); return opp; } static struct dev_pm_opp *_find_key_exact(struct device *dev, Loading Loading @@ -1345,11 +1326,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, */ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); struct dev_pm_opp *opp __free(put_opp) = NULL; unsigned long freq = 0, temp_freq; struct dev_pm_opp *opp = NULL; bool forced = false; int ret; opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { Loading @@ -1366,9 +1346,8 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) * equivalent to a clk_set_rate() */ if (!_get_opp_count(opp_table)) { ret = opp_table->config_clks(dev, opp_table, NULL, return opp_table->config_clks(dev, opp_table, NULL, &target_freq, false); goto put_opp_table; } freq = clk_round_rate(opp_table->clk, target_freq); Loading @@ -1383,10 +1362,9 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) temp_freq = freq; opp = _find_freq_ceil(opp_table, &temp_freq); if (IS_ERR(opp)) { ret = PTR_ERR(opp); dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n", __func__, freq, ret); goto put_opp_table; dev_err(dev, "%s: failed to find OPP for freq %lu (%ld)\n", __func__, freq, PTR_ERR(opp)); return PTR_ERR(opp); } /* Loading @@ -1399,14 +1377,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) forced = opp_table->current_rate_single_clk != freq; } ret = _set_opp(dev, opp_table, opp, &freq, forced); if (freq) dev_pm_opp_put(opp); put_opp_table: dev_pm_opp_put_opp_table(opp_table); return ret; return _set_opp(dev, opp_table, opp, &freq, forced); } EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate); Loading @@ -1422,8 +1393,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate); */ int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp) { struct opp_table *opp_table; int ret; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { Loading @@ -1431,10 +1401,7 @@ int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp) return PTR_ERR(opp_table); } ret = _set_opp(dev, opp_table, opp, NULL, false); dev_pm_opp_put_opp_table(opp_table); return ret; return _set_opp(dev, opp_table, opp, NULL, false); } EXPORT_SYMBOL_GPL(dev_pm_opp_set_opp); Loading Loading @@ -1744,15 +1711,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put); */ void dev_pm_opp_remove(struct device *dev, unsigned long freq) { struct opp_table *opp_table __free(put_opp_table); struct dev_pm_opp *opp = NULL, *iter; struct opp_table *opp_table; opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return; if (!assert_single_clk(opp_table, 0)) goto put_table; return; mutex_lock(&opp_table->lock); Loading @@ -1774,10 +1741,6 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n", __func__, freq); } put_table: /* Drop the reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_remove); Loading Loading @@ -1849,16 +1812,13 @@ bool _opp_remove_all_static(struct opp_table *opp_table) */ void dev_pm_opp_remove_all_dynamic(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return; _opp_remove_all(opp_table, true); /* Drop the reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic); Loading Loading @@ -2846,47 +2806,43 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_add_dynamic); static int _opp_set_availability(struct device *dev, unsigned long freq, bool availability_req) { struct opp_table *opp_table; struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); int r = 0; struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp; struct opp_table *opp_table __free(put_opp_table); /* Find the opp_table */ opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { r = PTR_ERR(opp_table); dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); return r; dev_warn(dev, "%s: Device OPP not found (%ld)\n", __func__, PTR_ERR(opp_table)); return PTR_ERR(opp_table); } if (!assert_single_clk(opp_table, 0)) { r = -EINVAL; goto put_table; } if (!assert_single_clk(opp_table, 0)) return -EINVAL; mutex_lock(&opp_table->lock); /* Do we have the frequency? */ list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { if (tmp_opp->rates[0] == freq) { opp = tmp_opp; break; } } if (IS_ERR(opp)) { r = PTR_ERR(opp); goto unlock; } opp = dev_pm_opp_get(tmp_opp); /* Is update really needed? */ if (opp->available == availability_req) goto unlock; if (opp->available == availability_req) { mutex_unlock(&opp_table->lock); return 0; } opp->available = availability_req; break; } } dev_pm_opp_get(opp); mutex_unlock(&opp_table->lock); if (IS_ERR(opp)) return PTR_ERR(opp); /* Notify the change of the OPP availability */ if (availability_req) blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ENABLE, Loading @@ -2895,14 +2851,7 @@ static int _opp_set_availability(struct device *dev, unsigned long freq, blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_DISABLE, opp); dev_pm_opp_put(opp); goto put_table; unlock: mutex_unlock(&opp_table->lock); put_table: dev_pm_opp_put_opp_table(opp_table); return r; return 0; } /** Loading @@ -2922,9 +2871,9 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, unsigned long u_volt_max) { struct opp_table *opp_table; struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); int r = 0; struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp; struct opp_table *opp_table __free(put_opp_table); int r; /* Find the opp_table */ opp_table = _find_opp_table(dev); Loading @@ -2934,49 +2883,40 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, return r; } if (!assert_single_clk(opp_table, 0)) { r = -EINVAL; goto put_table; } if (!assert_single_clk(opp_table, 0)) return -EINVAL; mutex_lock(&opp_table->lock); /* Do we have the frequency? */ list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { if (tmp_opp->rates[0] == freq) { opp = tmp_opp; break; } } if (IS_ERR(opp)) { r = PTR_ERR(opp); goto adjust_unlock; } opp = dev_pm_opp_get(tmp_opp); /* Is update really needed? */ if (opp->supplies->u_volt == u_volt) goto adjust_unlock; if (opp->supplies->u_volt == u_volt) { mutex_unlock(&opp_table->lock); return 0; } opp->supplies->u_volt = u_volt; opp->supplies->u_volt_min = u_volt_min; opp->supplies->u_volt_max = u_volt_max; dev_pm_opp_get(opp); break; } } mutex_unlock(&opp_table->lock); if (IS_ERR(opp)) return PTR_ERR(opp); /* Notify the voltage change of the OPP */ blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, opp); dev_pm_opp_put(opp); goto put_table; adjust_unlock: mutex_unlock(&opp_table->lock); put_table: dev_pm_opp_put_opp_table(opp_table); return r; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_adjust_voltage); Loading @@ -2990,9 +2930,9 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_adjust_voltage); */ int dev_pm_opp_sync_regulators(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); struct regulator *reg; int i, ret = 0; int ret, i; /* Device may not have OPP table */ opp_table = _find_opp_table(dev); Loading @@ -3001,23 +2941,20 @@ int dev_pm_opp_sync_regulators(struct device *dev) /* Regulator may not be required for the device */ if (unlikely(!opp_table->regulators)) goto put_table; return 0; /* Nothing to sync if voltage wasn't changed */ if (!opp_table->enabled) goto put_table; return 0; for (i = 0; i < opp_table->regulator_count; i++) { reg = opp_table->regulators[i]; ret = regulator_sync_voltage(reg); if (ret) break; return ret; } put_table: /* Drop reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); return ret; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_sync_regulators); Loading Loading @@ -3069,18 +3006,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_disable); */ int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb) { struct opp_table *opp_table; int ret; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return PTR_ERR(opp_table); ret = blocking_notifier_chain_register(&opp_table->head, nb); dev_pm_opp_put_opp_table(opp_table); return ret; return blocking_notifier_chain_register(&opp_table->head, nb); } EXPORT_SYMBOL(dev_pm_opp_register_notifier); Loading @@ -3094,18 +3026,13 @@ EXPORT_SYMBOL(dev_pm_opp_register_notifier); int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb) { struct opp_table *opp_table; int ret; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return PTR_ERR(opp_table); ret = blocking_notifier_chain_unregister(&opp_table->head, nb); dev_pm_opp_put_opp_table(opp_table); return ret; return blocking_notifier_chain_unregister(&opp_table->head, nb); } EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); Loading @@ -3118,7 +3045,7 @@ EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); */ void dev_pm_opp_remove_table(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); /* Check for existing table for 'dev' */ opp_table = _find_opp_table(dev); Loading @@ -3139,8 +3066,5 @@ void dev_pm_opp_remove_table(struct device *dev) **/ if (_opp_remove_all_static(opp_table)) dev_pm_opp_put_opp_table(opp_table); /* Drop reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_remove_table); drivers/opp/cpu.c +9 −18 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **opp_table) { struct dev_pm_opp *opp; struct cpufreq_frequency_table *freq_table = NULL; int i, max_opps, ret = 0; unsigned long rate; Loading @@ -57,6 +56,8 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, return -ENOMEM; for (i = 0, rate = 0; i < max_opps; i++, rate++) { struct dev_pm_opp *opp __free(put_opp); /* find next rate */ opp = dev_pm_opp_find_freq_ceil(dev, &rate); if (IS_ERR(opp)) { Loading @@ -69,8 +70,6 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, /* Is Boost/turbo opp ? */ if (dev_pm_opp_is_turbo(opp)) freq_table[i].flags = CPUFREQ_BOOST_FREQ; dev_pm_opp_put(opp); } freq_table[i].driver_data = i; Loading Loading @@ -155,10 +154,10 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table); int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask) { struct opp_table *opp_table __free(put_opp_table); struct opp_device *opp_dev; struct opp_table *opp_table; struct device *dev; int cpu, ret = 0; int cpu; opp_table = _find_opp_table(cpu_dev); if (IS_ERR(opp_table)) Loading Loading @@ -186,9 +185,7 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED; } dev_pm_opp_put_opp_table(opp_table); return ret; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); Loading @@ -204,18 +201,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); */ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) { struct opp_table *opp_table __free(put_opp_table); struct opp_device *opp_dev; struct opp_table *opp_table; int ret = 0; opp_table = _find_opp_table(cpu_dev); if (IS_ERR(opp_table)) return PTR_ERR(opp_table); if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) { ret = -EINVAL; goto put_opp_table; } if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) return -EINVAL; cpumask_clear(cpumask); Loading @@ -228,9 +222,6 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) cpumask_set_cpu(cpu_dev->id, cpumask); } put_opp_table: dev_pm_opp_put_opp_table(opp_table); return ret; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_sharing_cpus); drivers/opp/of.c +7 −17 Original line number Diff line number Diff line Loading @@ -1344,8 +1344,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus); int of_get_required_opp_performance_state(struct device_node *np, int index) { struct device_node *required_np __free(device_node); struct opp_table *opp_table; struct dev_pm_opp *opp; struct opp_table *opp_table __free(put_opp_table) = NULL; struct dev_pm_opp *opp __free(put_opp) = NULL; int pstate = -EINVAL; required_np = of_parse_required_opp(np, index); Loading Loading @@ -1373,11 +1373,8 @@ int of_get_required_opp_performance_state(struct device_node *np, int index) } else { pstate = opp->level; } dev_pm_opp_put(opp); } dev_pm_opp_put_opp_table(opp_table); return pstate; } EXPORT_SYMBOL_GPL(of_get_required_opp_performance_state); Loading Loading @@ -1443,7 +1440,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node); static int __maybe_unused _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) { struct dev_pm_opp *opp; struct dev_pm_opp *opp __free(put_opp); unsigned long opp_freq, opp_power; /* Find the right frequency and related OPP */ Loading @@ -1453,7 +1450,6 @@ _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) return -EINVAL; opp_power = dev_pm_opp_get_power(opp); dev_pm_opp_put(opp); if (!opp_power) return -EINVAL; Loading Loading @@ -1484,8 +1480,8 @@ _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW, unsigned long *kHz) { struct dev_pm_opp *opp __free(put_opp) = NULL; struct device_node *np __free(device_node); struct dev_pm_opp *opp; unsigned long mV, Hz; u32 cap; u64 tmp; Loading @@ -1505,7 +1501,6 @@ int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW, return -EINVAL; mV = dev_pm_opp_get_voltage(opp) / 1000; dev_pm_opp_put(opp); if (!mV) return -EINVAL; Loading @@ -1522,20 +1517,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_calc_power); static bool _of_has_opp_microwatt_property(struct device *dev) { unsigned long power, freq = 0; struct dev_pm_opp *opp; struct dev_pm_opp *opp __free(put_opp); unsigned long freq = 0; /* Check if at least one OPP has needed property */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); if (IS_ERR(opp)) return false; power = dev_pm_opp_get_power(opp); dev_pm_opp_put(opp); if (!power) return false; return true; return !!dev_pm_opp_get_power(opp); } /** Loading include/linux/pm_opp.h +7 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #ifndef __LINUX_OPP_H__ #define __LINUX_OPP_H__ #include <linux/cleanup.h> #include <linux/energy_model.h> #include <linux/err.h> #include <linux/notifier.h> Loading Loading @@ -579,6 +580,12 @@ static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_ta } #endif /* Scope based cleanup macro for OPP reference counting */ DEFINE_FREE(put_opp, struct dev_pm_opp *, if (!IS_ERR_OR_NULL(_T)) dev_pm_opp_put(_T)) /* Scope based cleanup macro for OPP table reference counting */ DEFINE_FREE(put_opp_table, struct opp_table *, if (!IS_ERR_OR_NULL(_T)) dev_pm_opp_put_opp_table(_T)) /* OPP Configuration helpers */ static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, Loading Loading
drivers/opp/core.c +79 −155 Original line number Diff line number Diff line Loading @@ -317,18 +317,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo); */ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) { struct opp_table *opp_table; unsigned long clock_latency_ns; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return 0; clock_latency_ns = opp_table->clock_latency_ns_max; dev_pm_opp_put_opp_table(opp_table); return clock_latency_ns; return opp_table->clock_latency_ns_max; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); Loading @@ -340,7 +335,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); */ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); struct dev_pm_opp *opp; struct regulator *reg; unsigned long latency_ns = 0; Loading @@ -356,13 +351,13 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) /* Regulator may not be required for the device */ if (!opp_table->regulators) goto put_opp_table; return 0; count = opp_table->regulator_count; uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL); if (!uV) goto put_opp_table; return 0; mutex_lock(&opp_table->lock); Loading Loading @@ -395,8 +390,6 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) } kfree(uV); put_opp_table: dev_pm_opp_put_opp_table(opp_table); return latency_ns; } Loading Loading @@ -426,7 +419,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_transition_latency); */ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); unsigned long freq = 0; opp_table = _find_opp_table(dev); Loading @@ -436,8 +429,6 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) if (opp_table->suspend_opp && opp_table->suspend_opp->available) freq = dev_pm_opp_get_freq(opp_table->suspend_opp); dev_pm_opp_put_opp_table(opp_table); return freq; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq); Loading Loading @@ -468,21 +459,16 @@ int _get_opp_count(struct opp_table *opp_table) */ int dev_pm_opp_get_opp_count(struct device *dev) { struct opp_table *opp_table; int count; struct opp_table *opp_table __free(put_opp_table); 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; dev_dbg(dev, "%s: OPP table not found (%ld)\n", __func__, PTR_ERR(opp_table)); return PTR_ERR(opp_table); } count = _get_opp_count(opp_table); dev_pm_opp_put_opp_table(opp_table); return count; return _get_opp_count(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); Loading Loading @@ -576,8 +562,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available, unsigned long opp_key, unsigned long key), bool (*assert)(struct opp_table *opp_table, unsigned int index)) { struct opp_table *opp_table; struct dev_pm_opp *opp; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { Loading @@ -586,12 +571,8 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available, return ERR_CAST(opp_table); } opp = _opp_table_find_key(opp_table, key, index, available, read, return _opp_table_find_key(opp_table, key, index, available, read, compare, assert); dev_pm_opp_put_opp_table(opp_table); return opp; } static struct dev_pm_opp *_find_key_exact(struct device *dev, Loading Loading @@ -1345,11 +1326,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, */ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); struct dev_pm_opp *opp __free(put_opp) = NULL; unsigned long freq = 0, temp_freq; struct dev_pm_opp *opp = NULL; bool forced = false; int ret; opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { Loading @@ -1366,9 +1346,8 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) * equivalent to a clk_set_rate() */ if (!_get_opp_count(opp_table)) { ret = opp_table->config_clks(dev, opp_table, NULL, return opp_table->config_clks(dev, opp_table, NULL, &target_freq, false); goto put_opp_table; } freq = clk_round_rate(opp_table->clk, target_freq); Loading @@ -1383,10 +1362,9 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) temp_freq = freq; opp = _find_freq_ceil(opp_table, &temp_freq); if (IS_ERR(opp)) { ret = PTR_ERR(opp); dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n", __func__, freq, ret); goto put_opp_table; dev_err(dev, "%s: failed to find OPP for freq %lu (%ld)\n", __func__, freq, PTR_ERR(opp)); return PTR_ERR(opp); } /* Loading @@ -1399,14 +1377,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) forced = opp_table->current_rate_single_clk != freq; } ret = _set_opp(dev, opp_table, opp, &freq, forced); if (freq) dev_pm_opp_put(opp); put_opp_table: dev_pm_opp_put_opp_table(opp_table); return ret; return _set_opp(dev, opp_table, opp, &freq, forced); } EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate); Loading @@ -1422,8 +1393,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate); */ int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp) { struct opp_table *opp_table; int ret; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { Loading @@ -1431,10 +1401,7 @@ int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp) return PTR_ERR(opp_table); } ret = _set_opp(dev, opp_table, opp, NULL, false); dev_pm_opp_put_opp_table(opp_table); return ret; return _set_opp(dev, opp_table, opp, NULL, false); } EXPORT_SYMBOL_GPL(dev_pm_opp_set_opp); Loading Loading @@ -1744,15 +1711,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put); */ void dev_pm_opp_remove(struct device *dev, unsigned long freq) { struct opp_table *opp_table __free(put_opp_table); struct dev_pm_opp *opp = NULL, *iter; struct opp_table *opp_table; opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return; if (!assert_single_clk(opp_table, 0)) goto put_table; return; mutex_lock(&opp_table->lock); Loading @@ -1774,10 +1741,6 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n", __func__, freq); } put_table: /* Drop the reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_remove); Loading Loading @@ -1849,16 +1812,13 @@ bool _opp_remove_all_static(struct opp_table *opp_table) */ void dev_pm_opp_remove_all_dynamic(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return; _opp_remove_all(opp_table, true); /* Drop the reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic); Loading Loading @@ -2846,47 +2806,43 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_add_dynamic); static int _opp_set_availability(struct device *dev, unsigned long freq, bool availability_req) { struct opp_table *opp_table; struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); int r = 0; struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp; struct opp_table *opp_table __free(put_opp_table); /* Find the opp_table */ opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) { r = PTR_ERR(opp_table); dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); return r; dev_warn(dev, "%s: Device OPP not found (%ld)\n", __func__, PTR_ERR(opp_table)); return PTR_ERR(opp_table); } if (!assert_single_clk(opp_table, 0)) { r = -EINVAL; goto put_table; } if (!assert_single_clk(opp_table, 0)) return -EINVAL; mutex_lock(&opp_table->lock); /* Do we have the frequency? */ list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { if (tmp_opp->rates[0] == freq) { opp = tmp_opp; break; } } if (IS_ERR(opp)) { r = PTR_ERR(opp); goto unlock; } opp = dev_pm_opp_get(tmp_opp); /* Is update really needed? */ if (opp->available == availability_req) goto unlock; if (opp->available == availability_req) { mutex_unlock(&opp_table->lock); return 0; } opp->available = availability_req; break; } } dev_pm_opp_get(opp); mutex_unlock(&opp_table->lock); if (IS_ERR(opp)) return PTR_ERR(opp); /* Notify the change of the OPP availability */ if (availability_req) blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ENABLE, Loading @@ -2895,14 +2851,7 @@ static int _opp_set_availability(struct device *dev, unsigned long freq, blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_DISABLE, opp); dev_pm_opp_put(opp); goto put_table; unlock: mutex_unlock(&opp_table->lock); put_table: dev_pm_opp_put_opp_table(opp_table); return r; return 0; } /** Loading @@ -2922,9 +2871,9 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, unsigned long u_volt_max) { struct opp_table *opp_table; struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); int r = 0; struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp; struct opp_table *opp_table __free(put_opp_table); int r; /* Find the opp_table */ opp_table = _find_opp_table(dev); Loading @@ -2934,49 +2883,40 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, return r; } if (!assert_single_clk(opp_table, 0)) { r = -EINVAL; goto put_table; } if (!assert_single_clk(opp_table, 0)) return -EINVAL; mutex_lock(&opp_table->lock); /* Do we have the frequency? */ list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { if (tmp_opp->rates[0] == freq) { opp = tmp_opp; break; } } if (IS_ERR(opp)) { r = PTR_ERR(opp); goto adjust_unlock; } opp = dev_pm_opp_get(tmp_opp); /* Is update really needed? */ if (opp->supplies->u_volt == u_volt) goto adjust_unlock; if (opp->supplies->u_volt == u_volt) { mutex_unlock(&opp_table->lock); return 0; } opp->supplies->u_volt = u_volt; opp->supplies->u_volt_min = u_volt_min; opp->supplies->u_volt_max = u_volt_max; dev_pm_opp_get(opp); break; } } mutex_unlock(&opp_table->lock); if (IS_ERR(opp)) return PTR_ERR(opp); /* Notify the voltage change of the OPP */ blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, opp); dev_pm_opp_put(opp); goto put_table; adjust_unlock: mutex_unlock(&opp_table->lock); put_table: dev_pm_opp_put_opp_table(opp_table); return r; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_adjust_voltage); Loading @@ -2990,9 +2930,9 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_adjust_voltage); */ int dev_pm_opp_sync_regulators(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); struct regulator *reg; int i, ret = 0; int ret, i; /* Device may not have OPP table */ opp_table = _find_opp_table(dev); Loading @@ -3001,23 +2941,20 @@ int dev_pm_opp_sync_regulators(struct device *dev) /* Regulator may not be required for the device */ if (unlikely(!opp_table->regulators)) goto put_table; return 0; /* Nothing to sync if voltage wasn't changed */ if (!opp_table->enabled) goto put_table; return 0; for (i = 0; i < opp_table->regulator_count; i++) { reg = opp_table->regulators[i]; ret = regulator_sync_voltage(reg); if (ret) break; return ret; } put_table: /* Drop reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); return ret; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_sync_regulators); Loading Loading @@ -3069,18 +3006,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_disable); */ int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb) { struct opp_table *opp_table; int ret; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return PTR_ERR(opp_table); ret = blocking_notifier_chain_register(&opp_table->head, nb); dev_pm_opp_put_opp_table(opp_table); return ret; return blocking_notifier_chain_register(&opp_table->head, nb); } EXPORT_SYMBOL(dev_pm_opp_register_notifier); Loading @@ -3094,18 +3026,13 @@ EXPORT_SYMBOL(dev_pm_opp_register_notifier); int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb) { struct opp_table *opp_table; int ret; struct opp_table *opp_table __free(put_opp_table); opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) return PTR_ERR(opp_table); ret = blocking_notifier_chain_unregister(&opp_table->head, nb); dev_pm_opp_put_opp_table(opp_table); return ret; return blocking_notifier_chain_unregister(&opp_table->head, nb); } EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); Loading @@ -3118,7 +3045,7 @@ EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); */ void dev_pm_opp_remove_table(struct device *dev) { struct opp_table *opp_table; struct opp_table *opp_table __free(put_opp_table); /* Check for existing table for 'dev' */ opp_table = _find_opp_table(dev); Loading @@ -3139,8 +3066,5 @@ void dev_pm_opp_remove_table(struct device *dev) **/ if (_opp_remove_all_static(opp_table)) dev_pm_opp_put_opp_table(opp_table); /* Drop reference taken by _find_opp_table() */ dev_pm_opp_put_opp_table(opp_table); } EXPORT_SYMBOL_GPL(dev_pm_opp_remove_table);
drivers/opp/cpu.c +9 −18 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, struct cpufreq_frequency_table **opp_table) { struct dev_pm_opp *opp; struct cpufreq_frequency_table *freq_table = NULL; int i, max_opps, ret = 0; unsigned long rate; Loading @@ -57,6 +56,8 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, return -ENOMEM; for (i = 0, rate = 0; i < max_opps; i++, rate++) { struct dev_pm_opp *opp __free(put_opp); /* find next rate */ opp = dev_pm_opp_find_freq_ceil(dev, &rate); if (IS_ERR(opp)) { Loading @@ -69,8 +70,6 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev, /* Is Boost/turbo opp ? */ if (dev_pm_opp_is_turbo(opp)) freq_table[i].flags = CPUFREQ_BOOST_FREQ; dev_pm_opp_put(opp); } freq_table[i].driver_data = i; Loading Loading @@ -155,10 +154,10 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table); int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask) { struct opp_table *opp_table __free(put_opp_table); struct opp_device *opp_dev; struct opp_table *opp_table; struct device *dev; int cpu, ret = 0; int cpu; opp_table = _find_opp_table(cpu_dev); if (IS_ERR(opp_table)) Loading Loading @@ -186,9 +185,7 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED; } dev_pm_opp_put_opp_table(opp_table); return ret; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); Loading @@ -204,18 +201,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); */ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) { struct opp_table *opp_table __free(put_opp_table); struct opp_device *opp_dev; struct opp_table *opp_table; int ret = 0; opp_table = _find_opp_table(cpu_dev); if (IS_ERR(opp_table)) return PTR_ERR(opp_table); if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) { ret = -EINVAL; goto put_opp_table; } if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) return -EINVAL; cpumask_clear(cpumask); Loading @@ -228,9 +222,6 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) cpumask_set_cpu(cpu_dev->id, cpumask); } put_opp_table: dev_pm_opp_put_opp_table(opp_table); return ret; return 0; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_sharing_cpus);
drivers/opp/of.c +7 −17 Original line number Diff line number Diff line Loading @@ -1344,8 +1344,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus); int of_get_required_opp_performance_state(struct device_node *np, int index) { struct device_node *required_np __free(device_node); struct opp_table *opp_table; struct dev_pm_opp *opp; struct opp_table *opp_table __free(put_opp_table) = NULL; struct dev_pm_opp *opp __free(put_opp) = NULL; int pstate = -EINVAL; required_np = of_parse_required_opp(np, index); Loading Loading @@ -1373,11 +1373,8 @@ int of_get_required_opp_performance_state(struct device_node *np, int index) } else { pstate = opp->level; } dev_pm_opp_put(opp); } dev_pm_opp_put_opp_table(opp_table); return pstate; } EXPORT_SYMBOL_GPL(of_get_required_opp_performance_state); Loading Loading @@ -1443,7 +1440,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node); static int __maybe_unused _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) { struct dev_pm_opp *opp; struct dev_pm_opp *opp __free(put_opp); unsigned long opp_freq, opp_power; /* Find the right frequency and related OPP */ Loading @@ -1453,7 +1450,6 @@ _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) return -EINVAL; opp_power = dev_pm_opp_get_power(opp); dev_pm_opp_put(opp); if (!opp_power) return -EINVAL; Loading Loading @@ -1484,8 +1480,8 @@ _get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz) int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW, unsigned long *kHz) { struct dev_pm_opp *opp __free(put_opp) = NULL; struct device_node *np __free(device_node); struct dev_pm_opp *opp; unsigned long mV, Hz; u32 cap; u64 tmp; Loading @@ -1505,7 +1501,6 @@ int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW, return -EINVAL; mV = dev_pm_opp_get_voltage(opp) / 1000; dev_pm_opp_put(opp); if (!mV) return -EINVAL; Loading @@ -1522,20 +1517,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_calc_power); static bool _of_has_opp_microwatt_property(struct device *dev) { unsigned long power, freq = 0; struct dev_pm_opp *opp; struct dev_pm_opp *opp __free(put_opp); unsigned long freq = 0; /* Check if at least one OPP has needed property */ opp = dev_pm_opp_find_freq_ceil(dev, &freq); if (IS_ERR(opp)) return false; power = dev_pm_opp_get_power(opp); dev_pm_opp_put(opp); if (!power) return false; return true; return !!dev_pm_opp_get_power(opp); } /** Loading
include/linux/pm_opp.h +7 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ #ifndef __LINUX_OPP_H__ #define __LINUX_OPP_H__ #include <linux/cleanup.h> #include <linux/energy_model.h> #include <linux/err.h> #include <linux/notifier.h> Loading Loading @@ -579,6 +580,12 @@ static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_ta } #endif /* Scope based cleanup macro for OPP reference counting */ DEFINE_FREE(put_opp, struct dev_pm_opp *, if (!IS_ERR_OR_NULL(_T)) dev_pm_opp_put(_T)) /* Scope based cleanup macro for OPP table reference counting */ DEFINE_FREE(put_opp_table, struct opp_table *, if (!IS_ERR_OR_NULL(_T)) dev_pm_opp_put_opp_table(_T)) /* OPP Configuration helpers */ static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, Loading