aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2023-02-24 07:09:26 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2023-02-24 07:44:07 +0530
commit48230ddb7976407319442fb369d9ae40fffe44af (patch)
treeb7274825eb67a10dc36e18c89028ea833764ddec
parent63ba794f1ab2975ff5174d77c96a7b2ee73cbb89 (diff)
OPP: Use set_required_opp() callback only for non-genpd devicesopp/propagate
Users may depend on both genpd and non-genpd devices, use set_required_opp() callback only for non-genpd cases. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/opp/core.c130
-rw-r--r--drivers/opp/of.c3
-rw-r--r--drivers/opp/opp.h8
-rw-r--r--include/linux/pm_opp.h9
4 files changed, 68 insertions, 82 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 22985ad7af79..d0a5096e64c4 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -935,14 +935,19 @@ static int _set_opp_bw(const struct opp_table *opp_table,
return 0;
}
-static int _set_performance_state(struct device *dev, struct device *pd_dev,
- struct dev_pm_opp *opp, int i)
+static int _set_required_opps_genpd(struct device *dev,
+ struct opp_table *opp_table, struct dev_pm_opp *opp, int i)
{
+ struct device *pd_dev = opp_table->genpd_virt_devs ?
+ opp_table->genpd_virt_devs[i] : dev;
unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0;
int ret;
- if (!pd_dev)
- return 0;
+ /*
+ * Acquire genpd_virt_dev_lock to make sure we don't use a genpd_dev
+ * after it is freed from another thread.
+ */
+ mutex_lock(&opp_table->genpd_virt_dev_lock);
ret = dev_pm_genpd_set_performance_state(pd_dev, pstate);
if (ret) {
@@ -950,77 +955,58 @@ static int _set_performance_state(struct device *dev, struct device *pd_dev,
dev_name(pd_dev), pstate, ret);
}
+ mutex_unlock(&opp_table->genpd_virt_dev_lock);
+
return ret;
}
-static int _opp_set_required_opps_generic(struct device *dev,
- struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down)
+static int _set_required_opps_default(struct device *dev,
+ struct dev_pm_opp *opp, struct dev_pm_opp *required_opp)
{
dev_err(dev, "setting required-opps isn't supported for non-genpd devices\n");
return -ENOENT;
}
-static int _opp_set_required_opps_genpd(struct device *dev,
- struct opp_table *opp_table, struct dev_pm_opp *opp, bool scaling_down)
+static int _set_required_opp(struct device *dev, struct opp_table *opp_table,
+ struct dev_pm_opp *opp, int i)
{
- struct device **genpd_virt_devs =
- opp_table->genpd_virt_devs ? opp_table->genpd_virt_devs : &dev;
- int i, ret = 0;
+ if (opp_table->required_opp_tables[i]->is_genpd)
+ return _set_required_opps_genpd(dev, opp_table, opp, i);
+ else
+ return opp_table->set_required_opp(dev, opp, opp->required_opps[i]);
+}
- /*
- * Acquire genpd_virt_dev_lock to make sure we don't use a genpd_dev
- * after it is freed from another thread.
- */
- mutex_lock(&opp_table->genpd_virt_dev_lock);
+/* 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 scaling_down)
+{
+ int i, ret;
+
+ if (!opp_table->required_opp_tables)
+ return 0;
+
+ /* required-opps not fully initialized yet */
+ if (lazy_linking_pending(opp_table))
+ return -EBUSY;
/* Scaling up? Set required OPPs in normal order, else reverse */
if (!scaling_down) {
for (i = 0; i < opp_table->required_opp_count; i++) {
- ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i);
+ ret = _set_required_opp(dev, opp_table, opp, i);
if (ret)
- break;
+ return ret;
}
} else {
for (i = opp_table->required_opp_count - 1; i >= 0; i--) {
- ret = _set_performance_state(dev, genpd_virt_devs[i], opp, i);
+ ret = _set_required_opp(dev, opp_table, opp, i);
if (ret)
- break;
+ return ret;
}
}
- mutex_unlock(&opp_table->genpd_virt_dev_lock);
-
- 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);
@@ -1068,7 +1054,7 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
if (opp_table->regulators)
regulator_disable(opp_table->regulators[0]);
- ret = _set_required_opps(dev, opp_table, NULL, false);
+ ret = _set_required_opps(dev, opp_table, NULL, true);
opp_table->enabled = false;
return ret;
@@ -1106,7 +1092,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
/* Scaling up? Configure required OPPs before frequency */
if (!scaling_down) {
- ret = _set_required_opps(dev, opp_table, opp, true);
+ ret = _set_required_opps(dev, opp_table, opp, scaling_down);
if (ret) {
dev_err(dev, "Failed to set required opps: %d\n", ret);
return ret;
@@ -1155,7 +1141,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
- ret = _set_required_opps(dev, opp_table, opp, false);
+ ret = _set_required_opps(dev, opp_table, opp, scaling_down);
if (ret) {
dev_err(dev, "Failed to set required opps: %d\n", ret);
return ret;
@@ -1329,6 +1315,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
INIT_LIST_HEAD(&opp_table->lazy);
opp_table->clk = ERR_PTR(-ENODEV);
+ opp_table->set_required_opp = _set_required_opps_default;
/* Mark regulator count uninitialized */
opp_table->regulator_count = -1;
@@ -2422,34 +2409,35 @@ static void _opp_detach_genpd(struct opp_table *opp_table)
}
/**
- * _opp_set_required_opps_helper() - Register custom set required opps helper.
+ * _opp_set_required_opp_helper() - Register custom set required opp helper.
* @dev: Device for which the helper is getting registered.
- * @set_required_opps: Custom set required opps helper.
+ * @set_required_opp: Custom set required opp helper.
*
- * This must be called before any OPPs are initialized for the device.
+ * This must be called before any OPPs are initialized for the device and this
+ * is called once for each non-genpd required OPP.
*/
-static void _opp_set_required_opps_helper(struct opp_table *opp_table,
- set_required_opps_t set_required_opps)
+static void _opp_set_required_opp_helper(struct opp_table *opp_table,
+ set_required_opp_t set_required_opp)
{
- opp_table->set_required_opps = set_required_opps;
+ opp_table->set_required_opp = set_required_opp;
}
/**
- * _opp_put_required_opps_helper() - Releases resources blocked for
- * required opps helper.
- * @opp_table: OPP table returned from _opp_set_required_opps_helper().
+ * _opp_put_required_opp_helper() - Releases resources blocked for
+ * required opp helper.
+ * @opp_table: OPP table returned from _opp_set_required_opp_helper().
*
- * Release resources blocked for platform specific required opps helper.
+ * Release resources blocked for platform specific required opp helper.
*/
-static void _opp_put_required_opps_helper(struct opp_table *opp_table)
+static void _opp_put_required_opp_helper(struct opp_table *opp_table)
{
- opp_table->set_required_opps = NULL;
+ opp_table->set_required_opp = NULL;
}
static void _opp_clear_config(struct opp_config_data *data)
{
- if (data->flags & OPP_CONFIG_REQUIRED_OPPS)
- _opp_put_required_opps_helper(data->opp_table);
+ if (data->flags & OPP_CONFIG_SET_REQUIRED_OPP)
+ _opp_put_required_opp_helper(data->opp_table);
if (data->flags & OPP_CONFIG_GENPD)
_opp_detach_genpd(data->opp_table);
if (data->flags & OPP_CONFIG_REGULATOR)
@@ -2574,11 +2562,11 @@ int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config)
}
/* Required opps helper */
- if (config->set_required_opps) {
- _opp_set_required_opps_helper(opp_table,
- config->set_required_opps);
+ if (config->set_required_opp) {
+ _opp_set_required_opp_helper(opp_table,
+ config->set_required_opp);
- data->flags |= OPP_CONFIG_REQUIRED_OPPS;
+ data->flags |= OPP_CONFIG_SET_REQUIRED_OPP;
}
ret = xa_alloc(&opp_configs, &id, data, XA_LIMIT(1, INT_MAX),
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 93da3c797afc..e55c6095adf0 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -196,8 +196,6 @@ 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;
@@ -413,7 +411,6 @@ 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)
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index 54cfeb894f5d..3d09da60318f 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -35,7 +35,7 @@ extern struct list_head opp_tables, lazy_opp_tables;
#define OPP_CONFIG_PROP_NAME BIT(3)
#define OPP_CONFIG_SUPPORTED_HW BIT(4)
#define OPP_CONFIG_GENPD BIT(5)
-#define OPP_CONFIG_REQUIRED_OPPS BIT(6)
+#define OPP_CONFIG_SET_REQUIRED_OPP BIT(6)
/**
* struct opp_config_data - data for set config operations
@@ -185,7 +185,8 @@ 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.
+ * @set_required_opp: Helper responsible to set required OPP, called once for
+ * each non-genpd rrequired OPP.
* @dentry: debugfs dentry pointer of the real device directory (not links).
* @dentry_name: Name of the real dentry.
*
@@ -236,7 +237,7 @@ struct opp_table {
bool enabled;
bool genpd_performance_state;
bool is_genpd;
- set_required_opps_t set_required_opps;
+ set_required_opp_t set_required_opp;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
@@ -260,7 +261,6 @@ 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)
{
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 5a8c0cc50c96..8cd77606f22a 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -64,8 +64,8 @@ typedef int (*config_regulators_t)(struct device *dev,
typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table,
struct dev_pm_opp *opp, void *data, bool scaling_down);
-typedef int (*set_required_opps_t)(struct device *dev, struct opp_table *opp_table,
- struct dev_pm_opp *opp, bool scaling_down);
+typedef int (*set_required_opp_t)(struct device *dev, struct dev_pm_opp *opp,
+ struct dev_pm_opp *required_opp);
/**
* struct dev_pm_opp_config - Device OPP configuration values
@@ -79,7 +79,8 @@ typedef int (*set_required_opps_t)(struct device *dev, struct opp_table *opp_tab
* @genpd_names: Null terminated array of pointers containing names of genpd to
* attach.
* @virt_devs: Pointer to return the array of virtual devices.
- * @set_required_opps: Custom set required opps helper.
+ * @set_required_opp: Custom set required opp helper, called once for
+ * each non-genpd required OPP.
*
* This structure contains platform specific OPP configurations for the device.
*/
@@ -94,7 +95,7 @@ struct dev_pm_opp_config {
const char * const *regulator_names;
const char * const *genpd_names;
struct device ***virt_devs;
- set_required_opps_t set_required_opps;
+ set_required_opp_t set_required_opp;
};
#if defined(CONFIG_PM_OPP)