Commit 009884f3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm+acpi-4.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management and ACPI updates from Rafael Wysocki:
 "Included are: a somewhat late devfreq update which however is mostly
  fixes and cleanups with one new thing only (the PPMUv2 support on
  Exynos5433), an ACPI cpufreq driver fixup and two ACPI core cleanups
  related to preprocessor directives.

  Specifics:

   - Fix a memory allocation size in the devfreq core (Xiaolong Ye).

   - Fix a mistake in the exynos-ppmu DT binding (Javier Martinez
     Canillas).

   - Add support for PPMUv2 ((Platform Performance Monitoring Unit
     version 2.0) on the Exynos5433 SoCs (Chanwoo Choi).

   - Fix a type casting bug in the Exynos PPMU code (MyungJoo Ham).

   - Assorted devfreq code cleanups and optimizations (Javi Merino,
     MyungJoo Ham, Viresh Kumar).

   - Fix up the ACPI cpufreq driver to use a more lightweight way to get
     to its private data in the ->get() callback (Rafael J Wysocki).

   - Fix a CONFIG_ prefix bug in one of the ACPI drivers and make the
     ACPI subsystem use IS_ENABLED() instead of #ifdefs in function
     bodies (Sudeep Holla)"

* tag 'pm+acpi-4.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: acpi-cpufreq: Use cpufreq_cpu_get_raw() in ->get()
  ACPI: Eliminate CONFIG_.*{, _MODULE} #ifdef in favor of IS_ENABLED()
  ACPI: int340x_thermal: add missing CONFIG_ prefix
  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
parents d590b2d4 0f40314b
...@@ -315,14 +315,10 @@ static void acpi_bus_osc_support(void) ...@@ -315,14 +315,10 @@ static void acpi_bus_osc_support(void)
capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ if (IS_ENABLED(CONFIG_ACPI_PROCESSOR_AGGREGATOR))
defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT; if (IS_ENABLED(CONFIG_ACPI_PROCESSOR))
#endif capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
#endif
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
......
...@@ -33,13 +33,12 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = { ...@@ -33,13 +33,12 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = {
static int int340x_thermal_handler_attach(struct acpi_device *adev, static int int340x_thermal_handler_attach(struct acpi_device *adev,
const struct acpi_device_id *id) const struct acpi_device_id *id)
{ {
#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE) if (IS_ENABLED(CONFIG_INT340X_THERMAL))
acpi_create_platform_device(adev); acpi_create_platform_device(adev);
#elif defined(INTEL_SOC_DTS_THERMAL) || defined(INTEL_SOC_DTS_THERMAL_MODULE)
/* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */ /* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */
if (id->driver_data == INT3401_DEVICE) else if (IS_ENABLED(CONFIG_INTEL_SOC_DTS_THERMAL) &&
id->driver_data == INT3401_DEVICE)
acpi_create_platform_device(adev); acpi_create_platform_device(adev);
#endif
return 1; return 1;
} }
......
...@@ -375,12 +375,11 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu) ...@@ -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); pr_debug("get_cur_freq_on_cpu (%d)\n", cpu);
policy = cpufreq_cpu_get(cpu); policy = cpufreq_cpu_get_raw(cpu);
if (unlikely(!policy)) if (unlikely(!policy))
return 0; return 0;
data = policy->driver_data; data = policy->driver_data;
cpufreq_cpu_put(policy);
if (unlikely(!data || !data->freq_table)) if (unlikely(!data || !data->freq_table))
return 0; return 0;
......
...@@ -238,13 +238,13 @@ int cpufreq_generic_init(struct cpufreq_policy *policy, ...@@ -238,13 +238,13 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
} }
EXPORT_SYMBOL_GPL(cpufreq_generic_init); EXPORT_SYMBOL_GPL(cpufreq_generic_init);
/* Only for cpufreq core internal use */ struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
static struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
{ {
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
return policy && cpumask_test_cpu(cpu, policy->cpus) ? policy : NULL; 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) unsigned int cpufreq_generic_get(unsigned int cpu)
{ {
......
...@@ -53,7 +53,7 @@ static struct devfreq *find_device_devfreq(struct device *dev) ...@@ -53,7 +53,7 @@ static struct devfreq *find_device_devfreq(struct device *dev)
{ {
struct devfreq *tmp_devfreq; 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__); pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -133,7 +133,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name) ...@@ -133,7 +133,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
{ {
struct devfreq_governor *tmp_governor; 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__); pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -177,10 +177,10 @@ int update_devfreq(struct devfreq *devfreq) ...@@ -177,10 +177,10 @@ int update_devfreq(struct devfreq *devfreq)
return err; return err;
/* /*
* Adjust the freuqency with user freq and QoS. * Adjust the frequency with user freq and QoS.
* *
* List from the highest proiority * List from the highest priority
* max_freq (probably called by thermal when it's too hot) * max_freq
* min_freq * min_freq
*/ */
...@@ -482,7 +482,7 @@ struct devfreq *devfreq_add_device(struct device *dev, ...@@ -482,7 +482,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq->profile->max_state * devfreq->profile->max_state *
devfreq->profile->max_state, devfreq->profile->max_state,
GFP_KERNEL); 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, devfreq->profile->max_state,
GFP_KERNEL); GFP_KERNEL);
devfreq->last_stat_updated = jiffies; devfreq->last_stat_updated = jiffies;
......
...@@ -319,7 +319,8 @@ static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev, ...@@ -319,7 +319,8 @@ static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
case PPMU_PMNCNT3: case PPMU_PMNCNT3:
pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH); pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH);
pmcnt_low = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_LOW); 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; break;
} }
edata->load_count = load_count; edata->load_count = load_count;
......
...@@ -21,17 +21,20 @@ ...@@ -21,17 +21,20 @@
static int devfreq_simple_ondemand_func(struct devfreq *df, static int devfreq_simple_ondemand_func(struct devfreq *df,
unsigned long *freq) unsigned long *freq)
{ {
struct devfreq_dev_status stat; int err;
int err = df->profile->get_dev_status(df->dev.parent, &stat); struct devfreq_dev_status *stat;
unsigned long long a, b; unsigned long long a, b;
unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD; unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL; unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
struct devfreq_simple_ondemand_data *data = df->data; struct devfreq_simple_ondemand_data *data = df->data;
unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX; unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
err = devfreq_update_stats(df);
if (err) if (err)
return err; return err;
stat = &df->last_status;
if (data) { if (data) {
if (data->upthreshold) if (data->upthreshold)
dfso_upthreshold = data->upthreshold; dfso_upthreshold = data->upthreshold;
...@@ -43,41 +46,41 @@ static int devfreq_simple_ondemand_func(struct devfreq *df, ...@@ -43,41 +46,41 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
return -EINVAL; return -EINVAL;
/* Assume MAX if it is going to be divided by zero */ /* Assume MAX if it is going to be divided by zero */
if (stat.total_time == 0) { if (stat->total_time == 0) {
*freq = max; *freq = max;
return 0; return 0;
} }
/* Prevent overflow */ /* Prevent overflow */
if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) { if (stat->busy_time >= (1 << 24) || stat->total_time >= (1 << 24)) {
stat.busy_time >>= 7; stat->busy_time >>= 7;
stat.total_time >>= 7; stat->total_time >>= 7;
} }
/* Set MAX if it's busy enough */ /* Set MAX if it's busy enough */
if (stat.busy_time * 100 > if (stat->busy_time * 100 >
stat.total_time * dfso_upthreshold) { stat->total_time * dfso_upthreshold) {
*freq = max; *freq = max;
return 0; return 0;
} }
/* Set MAX if we do not know the initial frequency */ /* Set MAX if we do not know the initial frequency */
if (stat.current_frequency == 0) { if (stat->current_frequency == 0) {
*freq = max; *freq = max;
return 0; return 0;
} }
/* Keep the current frequency */ /* Keep the current frequency */
if (stat.busy_time * 100 > if (stat->busy_time * 100 >
stat.total_time * (dfso_upthreshold - dfso_downdifferential)) { stat->total_time * (dfso_upthreshold - dfso_downdifferential)) {
*freq = stat.current_frequency; *freq = stat->current_frequency;
return 0; return 0;
} }
/* Set the desired frequency based on the load */ /* Set the desired frequency based on the load */
a = stat.busy_time; a = stat->busy_time;
a *= stat.current_frequency; a *= stat->current_frequency;
b = div_u64(a, stat.total_time); b = div_u64(a, stat->total_time);
b *= 100; b *= 100;
b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2)); b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
*freq = (unsigned long) b; *freq = (unsigned long) b;
......
...@@ -541,18 +541,20 @@ static struct devfreq_dev_profile tegra_devfreq_profile = { ...@@ -541,18 +541,20 @@ static struct devfreq_dev_profile tegra_devfreq_profile = {
static int tegra_governor_get_target(struct devfreq *devfreq, static int tegra_governor_get_target(struct devfreq *devfreq,
unsigned long *freq) unsigned long *freq)
{ {
struct devfreq_dev_status stat; struct devfreq_dev_status *stat;
struct tegra_devfreq *tegra; struct tegra_devfreq *tegra;
struct tegra_devfreq_device *dev; struct tegra_devfreq_device *dev;
unsigned long target_freq = 0; unsigned long target_freq = 0;
unsigned int i; unsigned int i;
int err; int err;
err = devfreq->profile->get_dev_status(devfreq->dev.parent, &stat); err = devfreq_update_stats(devfreq);
if (err) if (err)
return err; return err;
tegra = stat.private_data; stat = &devfreq->last_status;
tegra = stat->private_data;
for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
dev = &tegra->devices[i]; dev = &tegra->devices[i];
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#if defined(CONFIG_ACPI_BUTTON) || defined(CONFIG_ACPI_BUTTON_MODULE) #if IS_ENABLED(CONFIG_ACPI_BUTTON)
extern int acpi_lid_notifier_register(struct notifier_block *nb); extern int acpi_lid_notifier_register(struct notifier_block *nb);
extern int acpi_lid_notifier_unregister(struct notifier_block *nb); extern int acpi_lid_notifier_unregister(struct notifier_block *nb);
extern int acpi_lid_open(void); extern int acpi_lid_open(void);
...@@ -20,6 +20,6 @@ static inline int acpi_lid_open(void) ...@@ -20,6 +20,6 @@ static inline int acpi_lid_open(void)
{ {
return 1; return 1;
} }
#endif /* defined(CONFIG_ACPI_BUTTON) || defined(CONFIG_ACPI_BUTTON_MODULE) */ #endif /* IS_ENABLED(CONFIG_ACPI_BUTTON) */
#endif /* ACPI_BUTTON_H */ #endif /* ACPI_BUTTON_H */
...@@ -24,7 +24,7 @@ enum acpi_backlight_type { ...@@ -24,7 +24,7 @@ enum acpi_backlight_type {
acpi_backlight_native, acpi_backlight_native,
}; };
#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) #if IS_ENABLED(CONFIG_ACPI_VIDEO)
extern int acpi_video_register(void); extern int acpi_video_register(void);
extern void acpi_video_unregister(void); extern void acpi_video_unregister(void);
extern int acpi_video_get_edid(struct acpi_device *device, int type, extern int acpi_video_get_edid(struct acpi_device *device, int type,
......
...@@ -127,9 +127,14 @@ struct cpufreq_policy { ...@@ -127,9 +127,14 @@ struct cpufreq_policy {
#define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/ #define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu); struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
void cpufreq_cpu_put(struct cpufreq_policy *policy); void cpufreq_cpu_put(struct cpufreq_policy *policy);
#else #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) static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{ {
return NULL; return NULL;
......
...@@ -65,7 +65,10 @@ struct devfreq_dev_status { ...@@ -65,7 +65,10 @@ struct devfreq_dev_status {
* The "flags" parameter's possible values are * The "flags" parameter's possible values are
* explained above with "DEVFREQ_FLAG_*" macros. * explained above with "DEVFREQ_FLAG_*" macros.
* @get_dev_status: The device should provide the current performance * @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 * @get_cur_freq: The device should provide the current frequency
* at which it is operating. * at which it is operating.
* @exit: An optional callback that is called when devfreq * @exit: An optional callback that is called when devfreq
...@@ -161,6 +164,7 @@ struct devfreq { ...@@ -161,6 +164,7 @@ struct devfreq {
struct delayed_work work; struct delayed_work work;
unsigned long previous_freq; unsigned long previous_freq;
struct devfreq_dev_status last_status;
void *data; /* private data for governors */ void *data; /* private data for governors */
...@@ -204,6 +208,19 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev, ...@@ -204,6 +208,19 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
extern void devm_devfreq_unregister_opp_notifier(struct device *dev, extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq); 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) #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
/** /**
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq * 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, ...@@ -289,6 +306,11 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq) struct devfreq *devfreq)
{ {
} }
static inline int devfreq_update_stats(struct devfreq *df)
{
return -EINVAL;
}
#endif /* CONFIG_PM_DEVFREQ */ #endif /* CONFIG_PM_DEVFREQ */
#endif /* __LINUX_DEVFREQ_H__ */ #endif /* __LINUX_DEVFREQ_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment