mirror of https://gitee.com/openkylin/linux.git
Power management and ACPI material for v4.3-rc2
- 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). / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJV/IoLAAoJEILEb/54YlRxoWEP/3P7xbQ0FETVcuY8TqqauH0r AgmXqz9XYKgLwBEVnElVZE7fFu+5u5UiwQYv1wGePfR5tXQ9gxFYjh7RxmnFQVPV nJaPWO00ukiy8BugPnLepoEiJe+feoyAqyGoEmbaJPFiqt6lwVDY6UPatZLu9cP5 /9oD8623hpvk73w9FRYBMY4cXewSl5QbzRUc9NhSlWGmZOOokWFsG7aKletVyWHa LQJ5JbrsNaR4y1mt6eIwKMNWeO+N/C8e45fcVOGjAR9H7C5b3eNByoTsKoFjEvn9 4yuIkJu8X4hFDVVH8J359hAYKNvdiHLmTMcUAmufO/BH3M2Bc2SwBdnLbg3xnWMF xQkSYZT2E+uiYPOy/l98s75rN1bFj5MH+zy0dz6Mkz/lWSMh5CNYZoVH42h1h24S fYKO4KmxZmf+Ufx+zv27shvi4I322bJ/AEPLYFv6LWETHeHYegF+YOlLiDdUQ0B/ UjLVkj/nLhToyG02Q5VlYGtOY3XBNOLuYM+3gMLiCdFRjsUN9d7FawZtbVGlF6ej 58uZgDIGeRaacEvgAUWSfqHf1BT6l/YUekz/CfdTLCOxnPMEzBC5zDxdZ/P4HoRV BEKuUYPr4dEt/miKM7vCPop2C50o3dqXbD+MyzN0XuxURsxyAcmLiNdzi8lLorRt aalkUNTfoKuo7Oje4AB4 =+ZST -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
009884f384
|
@ -315,14 +315,10 @@ static void acpi_bus_osc_support(void)
|
|||
|
||||
capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
|
||||
capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
|
||||
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
|
||||
defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
|
||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
|
||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_ACPI_PROCESSOR_AGGREGATOR))
|
||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
|
||||
if (IS_ENABLED(CONFIG_ACPI_PROCESSOR))
|
||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_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[] = {
|
|||
static int int340x_thermal_handler_attach(struct acpi_device *adev,
|
||||
const struct acpi_device_id *id)
|
||||
{
|
||||
#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE)
|
||||
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 */
|
||||
if (id->driver_data == INT3401_DEVICE)
|
||||
if (IS_ENABLED(CONFIG_INT340X_THERMAL))
|
||||
acpi_create_platform_device(adev);
|
||||
/* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */
|
||||
else if (IS_ENABLED(CONFIG_INTEL_SOC_DTS_THERMAL) &&
|
||||
id->driver_data == INT3401_DEVICE)
|
||||
acpi_create_platform_device(adev);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#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_unregister(struct notifier_block *nb);
|
||||
extern int acpi_lid_open(void);
|
||||
|
@ -20,6 +20,6 @@ static inline int acpi_lid_open(void)
|
|||
{
|
||||
return 1;
|
||||
}
|
||||
#endif /* defined(CONFIG_ACPI_BUTTON) || defined(CONFIG_ACPI_BUTTON_MODULE) */
|
||||
#endif /* IS_ENABLED(CONFIG_ACPI_BUTTON) */
|
||||
|
||||
#endif /* ACPI_BUTTON_H */
|
||||
|
|
|
@ -24,7 +24,7 @@ enum acpi_backlight_type {
|
|||
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 void acpi_video_unregister(void);
|
||||
extern int acpi_video_get_edid(struct acpi_device *device, int type,
|
||||
|
|
|
@ -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