forked from Minki/linux
Merge branches 'pm-cpufreq' and 'pm-devfreq'
* pm-cpufreq: cpufreq: acpi-cpufreq: Use cpufreq_cpu_get_raw() in ->get() * pm-devfreq: PM / devfreq: Fix incorrect type issue. PM / devfreq: tegra: Update governor to use devfreq_update_stats() PM / devfreq: comments for get_dev_status usage updated PM / devfreq: drop comment about thermal setting max_freq PM / devfreq: cache the last call to get_dev_status() PM / devfreq: Drop unlikely before IS_ERR(_OR_NULL) PM / devfreq: exynos-ppmu: bit-wise operation bugfix. PM / devfreq: exynos-ppmu: Update documentation to support PPMUv2 PM / devfreq: exynos-ppmu: Add the support of PPMUv2 for Exynos5433 PM / devfreq: event: Remove incorrect property in exynos-ppmu DT binding
This commit is contained in:
commit
7dc1d36e8e
@ -375,12 +375,11 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
|
||||
|
||||
pr_debug("get_cur_freq_on_cpu (%d)\n", cpu);
|
||||
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
policy = cpufreq_cpu_get_raw(cpu);
|
||||
if (unlikely(!policy))
|
||||
return 0;
|
||||
|
||||
data = policy->driver_data;
|
||||
cpufreq_cpu_put(policy);
|
||||
if (unlikely(!data || !data->freq_table))
|
||||
return 0;
|
||||
|
||||
|
@ -238,13 +238,13 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_generic_init);
|
||||
|
||||
/* Only for cpufreq core internal use */
|
||||
static struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
|
||||
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
|
||||
{
|
||||
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
|
||||
|
||||
return policy && cpumask_test_cpu(cpu, policy->cpus) ? policy : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_cpu_get_raw);
|
||||
|
||||
unsigned int cpufreq_generic_get(unsigned int cpu)
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ static struct devfreq *find_device_devfreq(struct device *dev)
|
||||
{
|
||||
struct devfreq *tmp_devfreq;
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(dev))) {
|
||||
if (IS_ERR_OR_NULL(dev)) {
|
||||
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
@ -133,7 +133,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
|
||||
{
|
||||
struct devfreq_governor *tmp_governor;
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(name))) {
|
||||
if (IS_ERR_OR_NULL(name)) {
|
||||
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
@ -177,10 +177,10 @@ int update_devfreq(struct devfreq *devfreq)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Adjust the freuqency with user freq and QoS.
|
||||
* Adjust the frequency with user freq and QoS.
|
||||
*
|
||||
* List from the highest proiority
|
||||
* max_freq (probably called by thermal when it's too hot)
|
||||
* List from the highest priority
|
||||
* max_freq
|
||||
* min_freq
|
||||
*/
|
||||
|
||||
@ -482,7 +482,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
|
||||
devfreq->profile->max_state *
|
||||
devfreq->profile->max_state,
|
||||
GFP_KERNEL);
|
||||
devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) *
|
||||
devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned long) *
|
||||
devfreq->profile->max_state,
|
||||
GFP_KERNEL);
|
||||
devfreq->last_stat_updated = jiffies;
|
||||
|
@ -319,7 +319,8 @@ static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
|
||||
case PPMU_PMNCNT3:
|
||||
pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH);
|
||||
pmcnt_low = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_LOW);
|
||||
load_count = (u64)((pmcnt_high & 0xff) << 32) + (u64)pmcnt_low;
|
||||
load_count = ((u64)((pmcnt_high & 0xff)) << 32)
|
||||
+ (u64)pmcnt_low;
|
||||
break;
|
||||
}
|
||||
edata->load_count = load_count;
|
||||
|
@ -21,17 +21,20 @@
|
||||
static int devfreq_simple_ondemand_func(struct devfreq *df,
|
||||
unsigned long *freq)
|
||||
{
|
||||
struct devfreq_dev_status stat;
|
||||
int err = df->profile->get_dev_status(df->dev.parent, &stat);
|
||||
int err;
|
||||
struct devfreq_dev_status *stat;
|
||||
unsigned long long a, b;
|
||||
unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
|
||||
unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
|
||||
struct devfreq_simple_ondemand_data *data = df->data;
|
||||
unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
|
||||
|
||||
err = devfreq_update_stats(df);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
stat = &df->last_status;
|
||||
|
||||
if (data) {
|
||||
if (data->upthreshold)
|
||||
dfso_upthreshold = data->upthreshold;
|
||||
@ -43,41 +46,41 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
|
||||
return -EINVAL;
|
||||
|
||||
/* Assume MAX if it is going to be divided by zero */
|
||||
if (stat.total_time == 0) {
|
||||
if (stat->total_time == 0) {
|
||||
*freq = max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prevent overflow */
|
||||
if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
|
||||
stat.busy_time >>= 7;
|
||||
stat.total_time >>= 7;
|
||||
if (stat->busy_time >= (1 << 24) || stat->total_time >= (1 << 24)) {
|
||||
stat->busy_time >>= 7;
|
||||
stat->total_time >>= 7;
|
||||
}
|
||||
|
||||
/* Set MAX if it's busy enough */
|
||||
if (stat.busy_time * 100 >
|
||||
stat.total_time * dfso_upthreshold) {
|
||||
if (stat->busy_time * 100 >
|
||||
stat->total_time * dfso_upthreshold) {
|
||||
*freq = max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set MAX if we do not know the initial frequency */
|
||||
if (stat.current_frequency == 0) {
|
||||
if (stat->current_frequency == 0) {
|
||||
*freq = max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Keep the current frequency */
|
||||
if (stat.busy_time * 100 >
|
||||
stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
|
||||
*freq = stat.current_frequency;
|
||||
if (stat->busy_time * 100 >
|
||||
stat->total_time * (dfso_upthreshold - dfso_downdifferential)) {
|
||||
*freq = stat->current_frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the desired frequency based on the load */
|
||||
a = stat.busy_time;
|
||||
a *= stat.current_frequency;
|
||||
b = div_u64(a, stat.total_time);
|
||||
a = stat->busy_time;
|
||||
a *= stat->current_frequency;
|
||||
b = div_u64(a, stat->total_time);
|
||||
b *= 100;
|
||||
b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
|
||||
*freq = (unsigned long) b;
|
||||
|
@ -541,18 +541,20 @@ static struct devfreq_dev_profile tegra_devfreq_profile = {
|
||||
static int tegra_governor_get_target(struct devfreq *devfreq,
|
||||
unsigned long *freq)
|
||||
{
|
||||
struct devfreq_dev_status stat;
|
||||
struct devfreq_dev_status *stat;
|
||||
struct tegra_devfreq *tegra;
|
||||
struct tegra_devfreq_device *dev;
|
||||
unsigned long target_freq = 0;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
err = devfreq->profile->get_dev_status(devfreq->dev.parent, &stat);
|
||||
err = devfreq_update_stats(devfreq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
tegra = stat.private_data;
|
||||
stat = &devfreq->last_status;
|
||||
|
||||
tegra = stat->private_data;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
||||
dev = &tegra->devices[i];
|
||||
|
@ -127,9 +127,14 @@ struct cpufreq_policy {
|
||||
#define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
|
||||
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
|
||||
void cpufreq_cpu_put(struct cpufreq_policy *policy);
|
||||
#else
|
||||
static inline struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -65,7 +65,10 @@ struct devfreq_dev_status {
|
||||
* The "flags" parameter's possible values are
|
||||
* explained above with "DEVFREQ_FLAG_*" macros.
|
||||
* @get_dev_status: The device should provide the current performance
|
||||
* status to devfreq, which is used by governors.
|
||||
* status to devfreq. Governors are recommended not to
|
||||
* use this directly. Instead, governors are recommended
|
||||
* to use devfreq_update_stats() along with
|
||||
* devfreq.last_status.
|
||||
* @get_cur_freq: The device should provide the current frequency
|
||||
* at which it is operating.
|
||||
* @exit: An optional callback that is called when devfreq
|
||||
@ -161,6 +164,7 @@ struct devfreq {
|
||||
struct delayed_work work;
|
||||
|
||||
unsigned long previous_freq;
|
||||
struct devfreq_dev_status last_status;
|
||||
|
||||
void *data; /* private data for governors */
|
||||
|
||||
@ -204,6 +208,19 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
|
||||
extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
|
||||
struct devfreq *devfreq);
|
||||
|
||||
/**
|
||||
* devfreq_update_stats() - update the last_status pointer in struct devfreq
|
||||
* @df: the devfreq instance whose status needs updating
|
||||
*
|
||||
* Governors are recommended to use this function along with last_status,
|
||||
* which allows other entities to reuse the last_status without affecting
|
||||
* the values fetched later by governors.
|
||||
*/
|
||||
static inline int devfreq_update_stats(struct devfreq *df)
|
||||
{
|
||||
return df->profile->get_dev_status(df->dev.parent, &df->last_status);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
|
||||
/**
|
||||
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
|
||||
@ -289,6 +306,11 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
|
||||
struct devfreq *devfreq)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int devfreq_update_stats(struct devfreq *df)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_PM_DEVFREQ */
|
||||
|
||||
#endif /* __LINUX_DEVFREQ_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user