mirror of https://gitee.com/openkylin/linux.git
Power management and ACPI fixes for 3.10-rc3
- Additional CPU ID for the intel_pstate driver from Dirk Brandewie. - More cpufreq fixes related to ARM big.LITTLE support and locking from Viresh Kumar. - VIA C7 cpufreq build fix from Rafał Bilski. - ACPI power management fix making it possible to use device power states regardless of the CONFIG_PM setting from Rafael J. Wysocki. - New ACPI video blacklist item from Bastian Triller. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJRoRZjAAoJEKhOf7ml8uNsv9wQAKAMs9J8k6XqgNPisFKetw+K hzCOsKFOpI0BQKFikgtWjhGre1SyNIRUvLXO7BHFHXYQW6cLvn1jAyJhvl+i4nvT eOa+vdGd6grWncbhIxeidoyk9hTZ6bdMWlTBvKUz5KpHzvp4YGC2jlvwFwqsJkpg nQ8Hcbrbhm4vz5h7EmrlYcELBNTi5LQtmnqlxtbn02GX75BFTpkCm5aLZWZNEUrE Hix8BhN41+hSy+K34ztHFlP5g/s/lIa9dOX1tewqSigkDB/qYYIt2lpdD2icOIOW qHAtvpZq8/fZOcoZ9KdFqKUjjbuKVavldb+YzGeTLQufOAwb4hgMRvAccdNFMHIW 9tVkp2TcK6K7pAYlXtgEf25ka7ulLWDBd4C662gZfpi+oPKx2BI/6m7J4VoTULeb 30hDMyZXrXWWvStwO05Pyno3W5lG+cn9jytc3hKkaFerb53NHcZHfb0Rih5NhDZD Ep09IuPE8fOT9KndY2kw/WwoZyJurYCbrgE+G1QyA+hsNPkNhPlGTxdL8vCqxM4K ZOaQQejpd1bXBSk8Koz8LRyQ38KJByvM64B0EDSP6BQUT+rlbkcvog1bJV+UdpbJ 4TlhrAFlobhRFQBqlIbRqMXFPH31YSm7wVK1eK/gEqNZI935Kd17YSFf8yyi2yli vBlmPkiPEIJHysps+tvd =Srt8 -----END PGP SIGNATURE----- Merge tag 'pm+acpi-3.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull power management and ACPI fixes from Rafael Wysocki: - Additional CPU ID for the intel_pstate driver from Dirk Brandewie. - More cpufreq fixes related to ARM big.LITTLE support and locking from Viresh Kumar. - VIA C7 cpufreq build fix from Rafał Bilski. - ACPI power management fix making it possible to use device power states regardless of the CONFIG_PM setting from Rafael J Wysocki. - New ACPI video blacklist item from Bastian Triller. * tag 'pm+acpi-3.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / video: Add "Asus UL30A" to ACPI video detect blacklist cpufreq: arm_big_little_dt: Instantiate as platform_driver cpufreq: arm_big_little_dt: Register driver only if DT has valid data cpufreq / e_powersaver: Fix linker error when ACPI processor is a module cpufreq / intel_pstate: Add additional supported CPU ID cpufreq: Drop rwsem lock around CPUFREQ_GOV_POLICY_EXIT ACPI / PM: Allow device power states to be used for CONFIG_PM unset
This commit is contained in:
commit
1aad08dc57
|
@ -24,7 +24,7 @@ acpi-y += nvs.o
|
|||
# Power management related files
|
||||
acpi-y += wakeup.o
|
||||
acpi-y += sleep.o
|
||||
acpi-$(CONFIG_PM) += device_pm.o
|
||||
acpi-y += device_pm.o
|
||||
acpi-$(CONFIG_ACPI_SLEEP) += proc.o
|
||||
|
||||
|
||||
|
|
|
@ -37,68 +37,6 @@
|
|||
#define _COMPONENT ACPI_POWER_COMPONENT
|
||||
ACPI_MODULE_NAME("device_pm");
|
||||
|
||||
static DEFINE_MUTEX(acpi_pm_notifier_lock);
|
||||
|
||||
/**
|
||||
* acpi_add_pm_notifier - Register PM notifier for given ACPI device.
|
||||
* @adev: ACPI device to add the notifier for.
|
||||
* @context: Context information to pass to the notifier routine.
|
||||
*
|
||||
* NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
|
||||
* PM wakeup events. For example, wakeup events may be generated for bridges
|
||||
* if one of the devices below the bridge is signaling wakeup, even if the
|
||||
* bridge itself doesn't have a wakeup GPE associated with it.
|
||||
*/
|
||||
acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
|
||||
acpi_notify_handler handler, void *context)
|
||||
{
|
||||
acpi_status status = AE_ALREADY_EXISTS;
|
||||
|
||||
mutex_lock(&acpi_pm_notifier_lock);
|
||||
|
||||
if (adev->wakeup.flags.notifier_present)
|
||||
goto out;
|
||||
|
||||
status = acpi_install_notify_handler(adev->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handler, context);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out;
|
||||
|
||||
adev->wakeup.flags.notifier_present = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_pm_notifier_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
|
||||
* @adev: ACPI device to remove the notifier from.
|
||||
*/
|
||||
acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
|
||||
acpi_notify_handler handler)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
mutex_lock(&acpi_pm_notifier_lock);
|
||||
|
||||
if (!adev->wakeup.flags.notifier_present)
|
||||
goto out;
|
||||
|
||||
status = acpi_remove_notify_handler(adev->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handler);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out;
|
||||
|
||||
adev->wakeup.flags.notifier_present = false;
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_pm_notifier_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_power_state_string - String representation of ACPI device power state.
|
||||
* @state: ACPI device power state to return the string representation of.
|
||||
|
@ -385,6 +323,69 @@ bool acpi_bus_power_manageable(acpi_handle handle)
|
|||
}
|
||||
EXPORT_SYMBOL(acpi_bus_power_manageable);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static DEFINE_MUTEX(acpi_pm_notifier_lock);
|
||||
|
||||
/**
|
||||
* acpi_add_pm_notifier - Register PM notifier for given ACPI device.
|
||||
* @adev: ACPI device to add the notifier for.
|
||||
* @context: Context information to pass to the notifier routine.
|
||||
*
|
||||
* NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
|
||||
* PM wakeup events. For example, wakeup events may be generated for bridges
|
||||
* if one of the devices below the bridge is signaling wakeup, even if the
|
||||
* bridge itself doesn't have a wakeup GPE associated with it.
|
||||
*/
|
||||
acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
|
||||
acpi_notify_handler handler, void *context)
|
||||
{
|
||||
acpi_status status = AE_ALREADY_EXISTS;
|
||||
|
||||
mutex_lock(&acpi_pm_notifier_lock);
|
||||
|
||||
if (adev->wakeup.flags.notifier_present)
|
||||
goto out;
|
||||
|
||||
status = acpi_install_notify_handler(adev->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handler, context);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out;
|
||||
|
||||
adev->wakeup.flags.notifier_present = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_pm_notifier_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
|
||||
* @adev: ACPI device to remove the notifier from.
|
||||
*/
|
||||
acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
|
||||
acpi_notify_handler handler)
|
||||
{
|
||||
acpi_status status = AE_BAD_PARAMETER;
|
||||
|
||||
mutex_lock(&acpi_pm_notifier_lock);
|
||||
|
||||
if (!adev->wakeup.flags.notifier_present)
|
||||
goto out;
|
||||
|
||||
status = acpi_remove_notify_handler(adev->handle,
|
||||
ACPI_SYSTEM_NOTIFY,
|
||||
handler);
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out;
|
||||
|
||||
adev->wakeup.flags.notifier_present = false;
|
||||
|
||||
out:
|
||||
mutex_unlock(&acpi_pm_notifier_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
bool acpi_bus_can_wakeup(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
|
@ -1023,3 +1024,4 @@ void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
|
|||
mutex_unlock(&adev->physical_node_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
|
||||
#endif /* CONFIG_PM */
|
||||
|
|
|
@ -161,6 +161,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
.ident = "Asus UL30A",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
|
||||
},
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ config X86_LONGHAUL
|
|||
config X86_E_POWERSAVER
|
||||
tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
|
||||
select CPU_FREQ_TABLE
|
||||
depends on X86_32
|
||||
depends on X86_32 && ACPI_PROCESSOR
|
||||
help
|
||||
This adds the CPUFreq driver for VIA C7 processors. However, this driver
|
||||
does not have any safeguards to prevent operating the CPU out of spec
|
||||
|
|
|
@ -19,70 +19,75 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/opp.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include "arm_big_little.h"
|
||||
|
||||
static int dt_init_opp_table(struct device *cpu_dev)
|
||||
/* get cpu node with valid operating-points */
|
||||
static struct device_node *get_cpu_node_with_valid_op(int cpu)
|
||||
{
|
||||
struct device_node *np, *parent;
|
||||
int count = 0, ret;
|
||||
|
||||
parent = of_find_node_by_path("/cpus");
|
||||
if (!parent) {
|
||||
pr_err("failed to find OF /cpus\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for_each_child_of_node(parent, np) {
|
||||
if (count++ != cpu_dev->id)
|
||||
continue;
|
||||
if (!of_get_property(np, "operating-points", NULL)) {
|
||||
ret = -ENODATA;
|
||||
} else {
|
||||
cpu_dev->of_node = np;
|
||||
ret = of_init_opp_table(cpu_dev);
|
||||
}
|
||||
of_node_put(np);
|
||||
of_node_put(parent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int dt_get_transition_latency(struct device *cpu_dev)
|
||||
{
|
||||
struct device_node *np, *parent;
|
||||
u32 transition_latency = CPUFREQ_ETERNAL;
|
||||
struct device_node *np = NULL, *parent;
|
||||
int count = 0;
|
||||
|
||||
parent = of_find_node_by_path("/cpus");
|
||||
if (!parent) {
|
||||
pr_info("Failed to find OF /cpus. Use CPUFREQ_ETERNAL transition latency\n");
|
||||
return CPUFREQ_ETERNAL;
|
||||
pr_err("failed to find OF /cpus\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for_each_child_of_node(parent, np) {
|
||||
if (count++ != cpu_dev->id)
|
||||
if (count++ != cpu)
|
||||
continue;
|
||||
if (!of_get_property(np, "operating-points", NULL)) {
|
||||
of_node_put(np);
|
||||
np = NULL;
|
||||
}
|
||||
|
||||
of_property_read_u32(np, "clock-latency", &transition_latency);
|
||||
of_node_put(np);
|
||||
of_node_put(parent);
|
||||
|
||||
return transition_latency;
|
||||
break;
|
||||
}
|
||||
|
||||
pr_info("clock-latency isn't found, use CPUFREQ_ETERNAL transition latency\n");
|
||||
return CPUFREQ_ETERNAL;
|
||||
of_node_put(parent);
|
||||
return np;
|
||||
}
|
||||
|
||||
static int dt_init_opp_table(struct device *cpu_dev)
|
||||
{
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
np = get_cpu_node_with_valid_op(cpu_dev->id);
|
||||
if (!np)
|
||||
return -ENODATA;
|
||||
|
||||
cpu_dev->of_node = np;
|
||||
ret = of_init_opp_table(cpu_dev);
|
||||
of_node_put(np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dt_get_transition_latency(struct device *cpu_dev)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 transition_latency = CPUFREQ_ETERNAL;
|
||||
|
||||
np = get_cpu_node_with_valid_op(cpu_dev->id);
|
||||
if (!np)
|
||||
return CPUFREQ_ETERNAL;
|
||||
|
||||
of_property_read_u32(np, "clock-latency", &transition_latency);
|
||||
of_node_put(np);
|
||||
|
||||
pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
|
||||
return transition_latency;
|
||||
}
|
||||
|
||||
static struct cpufreq_arm_bL_ops dt_bL_ops = {
|
||||
|
@ -91,17 +96,33 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = {
|
|||
.init_opp_table = dt_init_opp_table,
|
||||
};
|
||||
|
||||
static int generic_bL_init(void)
|
||||
static int generic_bL_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = get_cpu_node_with_valid_op(0);
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
of_node_put(np);
|
||||
return bL_cpufreq_register(&dt_bL_ops);
|
||||
}
|
||||
module_init(generic_bL_init);
|
||||
|
||||
static void generic_bL_exit(void)
|
||||
static int generic_bL_remove(struct platform_device *pdev)
|
||||
{
|
||||
return bL_cpufreq_unregister(&dt_bL_ops);
|
||||
bL_cpufreq_unregister(&dt_bL_ops);
|
||||
return 0;
|
||||
}
|
||||
module_exit(generic_bL_exit);
|
||||
|
||||
static struct platform_driver generic_bL_platdrv = {
|
||||
.driver = {
|
||||
.name = "arm-bL-cpufreq-dt",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = generic_bL_probe,
|
||||
.remove = generic_bL_remove,
|
||||
};
|
||||
module_platform_driver(generic_bL_platdrv);
|
||||
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
||||
MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
|
||||
|
|
|
@ -1729,18 +1729,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
|
|||
/* end old governor */
|
||||
if (data->governor) {
|
||||
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
|
||||
unlock_policy_rwsem_write(policy->cpu);
|
||||
__cpufreq_governor(data,
|
||||
CPUFREQ_GOV_POLICY_EXIT);
|
||||
lock_policy_rwsem_write(policy->cpu);
|
||||
}
|
||||
|
||||
/* start new governor */
|
||||
data->governor = policy->governor;
|
||||
if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
|
||||
if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
|
||||
if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
|
||||
failed = 0;
|
||||
else
|
||||
} else {
|
||||
unlock_policy_rwsem_write(policy->cpu);
|
||||
__cpufreq_governor(data,
|
||||
CPUFREQ_GOV_POLICY_EXIT);
|
||||
lock_policy_rwsem_write(policy->cpu);
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
|
|
|
@ -521,6 +521,7 @@ static void intel_pstate_timer_func(unsigned long __data)
|
|||
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
|
||||
ICPU(0x2a, default_policy),
|
||||
ICPU(0x2d, default_policy),
|
||||
ICPU(0x3a, default_policy),
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
|
||||
|
|
|
@ -377,7 +377,6 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
|
|||
unsigned long long *sta);
|
||||
int acpi_bus_get_status(struct acpi_device *device);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int acpi_bus_set_power(acpi_handle handle, int state);
|
||||
const char *acpi_power_state_string(int state);
|
||||
int acpi_device_get_power(struct acpi_device *device, int *state);
|
||||
|
@ -385,41 +384,12 @@ int acpi_device_set_power(struct acpi_device *device, int state);
|
|||
int acpi_bus_init_power(struct acpi_device *device);
|
||||
int acpi_bus_update_power(acpi_handle handle, int *state_p);
|
||||
bool acpi_bus_power_manageable(acpi_handle handle);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
bool acpi_bus_can_wakeup(acpi_handle handle);
|
||||
#else /* !CONFIG_PM */
|
||||
static inline int acpi_bus_set_power(acpi_handle handle, int state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline const char *acpi_power_state_string(int state)
|
||||
{
|
||||
return "D0";
|
||||
}
|
||||
static inline int acpi_device_get_power(struct acpi_device *device, int *state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int acpi_device_set_power(struct acpi_device *device, int state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int acpi_bus_init_power(struct acpi_device *device)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int acpi_bus_update_power(acpi_handle handle, int *state_p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline bool acpi_bus_power_manageable(acpi_handle handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool acpi_bus_can_wakeup(acpi_handle handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* !CONFIG_PM */
|
||||
#else
|
||||
static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI_PROC_EVENT
|
||||
int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);
|
||||
|
|
Loading…
Reference in New Issue