Skip to content

Commit 528f2d8

Browse files
committed
OPP: Move required opps configuration to specialized callback
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>
1 parent 29b1a92 commit 528f2d8

3 files changed

Lines changed: 49 additions & 27 deletions

File tree

drivers/opp/core.c

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,8 @@ static int _set_opp_bw(const struct opp_table *opp_table,
935935
return 0;
936936
}
937937

938-
static int _set_required_opp(struct device *dev, struct device *pd_dev,
939-
struct dev_pm_opp *opp, int i)
938+
static int _set_performance_state(struct device *dev, struct device *pd_dev,
939+
struct dev_pm_opp *opp, int i)
940940
{
941941
unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0;
942942
int ret;
@@ -953,49 +953,36 @@ static int _set_required_opp(struct device *dev, struct device *pd_dev,
953953
return ret;
954954
}
955955

956-
/* This is only called for PM domain for now */
957-
static int _set_required_opps(struct device *dev,
958-
struct opp_table *opp_table,
959-
struct dev_pm_opp *opp, bool up)
956+
static int _opp_set_required_opps_generic(struct device *dev,
957+
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down)
958+
{
959+
dev_err(dev, "setting required-opps isn't supported for non-genpd devices\n");
960+
return -ENOENT;
961+
}
962+
963+
static int _opp_set_required_opps_genpd(struct device *dev,
964+
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down)
960965
{
961-
struct opp_table **required_opp_tables = opp_table->required_opp_tables;
962966
struct device **genpd_virt_devs =
963967
opp_table->genpd_virt_devs ? opp_table->genpd_virt_devs : &dev;
964968
int i, ret = 0;
965969

966-
if (!required_opp_tables)
967-
return 0;
968-
969-
/* required-opps not fully initialized yet */
970-
if (lazy_linking_pending(opp_table))
971-
return -EBUSY;
972-
973-
/*
974-
* We only support genpd's OPPs in the "required-opps" for now, as we
975-
* don't know much about other use cases. Error out if the required OPP
976-
* doesn't belong to a genpd.
977-
*/
978-
if (unlikely(!required_opp_tables[0]->is_genpd)) {
979-
dev_err(dev, "required-opps don't belong to a genpd\n");
980-
return -ENOENT;
981-
}
982-
983970
/*
984971
* Acquire genpd_virt_dev_lock to make sure we don't use a genpd_dev
985972
* after it is freed from another thread.
986973
*/
987974
mutex_lock(&opp_table->genpd_virt_dev_lock);
988975

989976
/* Scaling up? Set required OPPs in normal order, else reverse */
990-
if (up) {
977+
if (!scaling_down) {
991978
for (i = 0; i < opp_table->required_opp_count; i++) {
992-
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
979+
ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i);
993980
if (ret)
994981
break;
995982
}
996983
} else {
997984
for (i = opp_table->required_opp_count - 1; i >= 0; i--) {
998-
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
985+
ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i);
999986
if (ret)
1000987
break;
1001988
}
@@ -1006,6 +993,34 @@ static int _set_required_opps(struct device *dev,
1006993
return ret;
1007994
}
1008995

996+
/* This is only called for PM domain for now */
997+
static int _set_required_opps(struct device *dev, struct opp_table *opp_table,
998+
struct dev_pm_opp *opp, bool up)
999+
{
1000+
/* required-opps not fully initialized yet */
1001+
if (lazy_linking_pending(opp_table))
1002+
return -EBUSY;
1003+
1004+
if (opp_table->set_required_opps)
1005+
return opp_table->set_required_opps(dev, opp_table, opp, up);
1006+
1007+
return 0;
1008+
}
1009+
1010+
/* Update set_required_opps handler */
1011+
void _update_set_required_opps(struct opp_table *opp_table)
1012+
{
1013+
/* Already set */
1014+
if (opp_table->set_required_opps)
1015+
return;
1016+
1017+
/* All required OPPs will belong to genpd or none */
1018+
if (opp_table->required_opp_tables[0]->is_genpd)
1019+
opp_table->set_required_opps = _opp_set_required_opps_genpd;
1020+
else
1021+
opp_table->set_required_opps = _opp_set_required_opps_generic;
1022+
}
1023+
10091024
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
10101025
{
10111026
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);

drivers/opp/of.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
196196
/* Let's do the linking later on */
197197
if (lazy)
198198
list_add(&opp_table->lazy, &lazy_opp_tables);
199+
else
200+
_update_set_required_opps(opp_table);
199201

200202
goto put_np;
201203

@@ -411,6 +413,7 @@ static void lazy_link_required_opp_table(struct opp_table *new_table)
411413

412414
/* All required opp-tables found, remove from lazy list */
413415
if (!lazy) {
416+
_update_set_required_opps(opp_table);
414417
list_del_init(&opp_table->lazy);
415418

416419
list_for_each_entry(opp, &opp_table->opp_list, node)

drivers/opp/opp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ enum opp_table_access {
184184
* @enabled: Set to true if the device's resources are enabled/configured.
185185
* @genpd_performance_state: Device's power domain support performance state.
186186
* @is_genpd: Marks if the OPP table belongs to a genpd.
187+
* @set_required_opps: Helper responsible to set required OPPs.
187188
* @dentry: debugfs dentry pointer of the real device directory (not links).
188189
* @dentry_name: Name of the real dentry.
189190
*
@@ -234,6 +235,8 @@ struct opp_table {
234235
bool enabled;
235236
bool genpd_performance_state;
236237
bool is_genpd;
238+
int (*set_required_opps)(struct device *dev,
239+
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down);
237240

238241
#ifdef CONFIG_DEBUG_FS
239242
struct dentry *dentry;
@@ -257,6 +260,7 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cp
257260
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
258261
void _put_opp_list_kref(struct opp_table *opp_table);
259262
void _required_opps_available(struct dev_pm_opp *opp, int count);
263+
void _update_set_required_opps(struct opp_table *opp_table);
260264

261265
static inline bool lazy_linking_pending(struct opp_table *opp_table)
262266
{

0 commit comments

Comments
 (0)