diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2023-02-24 07:09:26 +0530 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2023-02-24 07:44:07 +0530 |
commit | 48230ddb7976407319442fb369d9ae40fffe44af (patch) | |
tree | b7274825eb67a10dc36e18c89028ea833764ddec | |
parent | 63ba794f1ab2975ff5174d77c96a7b2ee73cbb89 (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.c | 130 | ||||
-rw-r--r-- | drivers/opp/of.c | 3 | ||||
-rw-r--r-- | drivers/opp/opp.h | 8 | ||||
-rw-r--r-- | include/linux/pm_opp.h | 9 |
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) |