Skip to content

Commit

Permalink
Merge tag 'opp-updates-6.4' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/vireshk/pm into pm-opp

Pull OPP updates for 6.4 from Viresh Kumar:

"- Use of_property_present() for testing DT property presence (Rob
   Herring).

 - Add set_required_opps() callback to the 'struct opp_table', to make
   the code paths cleaner (Viresh Kumar)."

* tag 'opp-updates-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  OPP: Move required opps configuration to specialized callback
  OPP: Handle all genpd cases together in _set_required_opps()
  opp: Use of_property_present() for testing DT property presence
  • Loading branch information
Rafael J. Wysocki committed Apr 18, 2023
2 parents 6a8f57a + 528f2d8 commit 0ba4962
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 36 deletions.
78 changes: 44 additions & 34 deletions drivers/opp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,8 +935,8 @@ static int _set_opp_bw(const struct opp_table *opp_table,
return 0;
}

static int _set_required_opp(struct device *dev, struct device *pd_dev,
struct dev_pm_opp *opp, int i)
static int _set_performance_state(struct device *dev, struct device *pd_dev,
struct dev_pm_opp *opp, int i)
{
unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0;
int ret;
Expand All @@ -953,37 +953,19 @@ static int _set_required_opp(struct device *dev, struct device *pd_dev,
return ret;
}

/* This is only called for PM domain for now */
static int _set_required_opps(struct device *dev,
struct opp_table *opp_table,
struct dev_pm_opp *opp, bool up)
static int _opp_set_required_opps_generic(struct device *dev,
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down)
{
struct opp_table **required_opp_tables = opp_table->required_opp_tables;
struct device **genpd_virt_devs = opp_table->genpd_virt_devs;
int i, ret = 0;

if (!required_opp_tables)
return 0;

/* required-opps not fully initialized yet */
if (lazy_linking_pending(opp_table))
return -EBUSY;

/*
* We only support genpd's OPPs in the "required-opps" for now, as we
* don't know much about other use cases. Error out if the required OPP
* doesn't belong to a genpd.
*/
if (unlikely(!required_opp_tables[0]->is_genpd)) {
dev_err(dev, "required-opps don't belong to a genpd\n");
return -ENOENT;
}

/* Single genpd case */
if (!genpd_virt_devs)
return _set_required_opp(dev, dev, opp, 0);
dev_err(dev, "setting required-opps isn't supported for non-genpd devices\n");
return -ENOENT;
}

/* Multiple genpd case */
static int _opp_set_required_opps_genpd(struct device *dev,
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down)
{
struct device **genpd_virt_devs =
opp_table->genpd_virt_devs ? opp_table->genpd_virt_devs : &dev;
int i, ret = 0;

/*
* Acquire genpd_virt_dev_lock to make sure we don't use a genpd_dev
Expand All @@ -992,15 +974,15 @@ static int _set_required_opps(struct device *dev,
mutex_lock(&opp_table->genpd_virt_dev_lock);

/* Scaling up? Set required OPPs in normal order, else reverse */
if (up) {
if (!scaling_down) {
for (i = 0; i < opp_table->required_opp_count; i++) {
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i);
if (ret)
break;
}
} else {
for (i = opp_table->required_opp_count - 1; i >= 0; i--) {
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i);
if (ret)
break;
}
Expand All @@ -1011,6 +993,34 @@ static int _set_required_opps(struct device *dev,
return ret;
}

/* This is only called for PM domain for now */
static int _set_required_opps(struct device *dev, struct opp_table *opp_table,
struct dev_pm_opp *opp, bool up)
{
/* required-opps not fully initialized yet */
if (lazy_linking_pending(opp_table))
return -EBUSY;

if (opp_table->set_required_opps)
return opp_table->set_required_opps(dev, opp_table, opp, up);

return 0;
}

/* Update set_required_opps handler */
void _update_set_required_opps(struct opp_table *opp_table)
{
/* Already set */
if (opp_table->set_required_opps)
return;

/* All required OPPs will belong to genpd or none */
if (opp_table->required_opp_tables[0]->is_genpd)
opp_table->set_required_opps = _opp_set_required_opps_genpd;
else
opp_table->set_required_opps = _opp_set_required_opps_generic;
}

static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
{
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
Expand Down
7 changes: 5 additions & 2 deletions drivers/opp/of.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
/* Let's do the linking later on */
if (lazy)
list_add(&opp_table->lazy, &lazy_opp_tables);
else
_update_set_required_opps(opp_table);

goto put_np;

Expand Down Expand Up @@ -224,7 +226,7 @@ void _of_init_opp_table(struct opp_table *opp_table, struct device *dev,
of_property_read_u32(np, "voltage-tolerance",
&opp_table->voltage_tolerance_v1);

if (of_find_property(np, "#power-domain-cells", NULL))
if (of_property_present(np, "#power-domain-cells"))
opp_table->is_genpd = true;

/* Get OPP table node */
Expand Down Expand Up @@ -411,6 +413,7 @@ static void lazy_link_required_opp_table(struct opp_table *new_table)

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

list_for_each_entry(opp, &opp_table->opp_list, node)
Expand Down Expand Up @@ -536,7 +539,7 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
* an OPP then the OPP should not be enabled as there is
* no way to see if the hardware supports it.
*/
if (of_find_property(np, "opp-supported-hw", NULL))
if (of_property_present(np, "opp-supported-hw"))
return false;
else
return true;
Expand Down
4 changes: 4 additions & 0 deletions drivers/opp/opp.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ enum opp_table_access {
* @enabled: Set to true if the device's resources are enabled/configured.
* @genpd_performance_state: Device's power domain support performance state.
* @is_genpd: Marks if the OPP table belongs to a genpd.
* @set_required_opps: Helper responsible to set required OPPs.
* @dentry: debugfs dentry pointer of the real device directory (not links).
* @dentry_name: Name of the real dentry.
*
Expand Down Expand Up @@ -234,6 +235,8 @@ struct opp_table {
bool enabled;
bool genpd_performance_state;
bool is_genpd;
int (*set_required_opps)(struct device *dev,
struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down);

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

static inline bool lazy_linking_pending(struct opp_table *opp_table)
{
Expand Down

0 comments on commit 0ba4962

Please sign in to comment.