Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1aad08dc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 27a24cfa 5a2bff8d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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


+64 −62
Original line number Diff line number Diff line
@@ -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 */
+8 −0
Original line number Diff line number Diff line
@@ -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"),
		},
	},
	{ },
};

+1 −1
Original line number Diff line number Diff line
@@ -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
+57 −36
Original line number Diff line number Diff line
@@ -19,89 +19,110 @@

#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;
	struct device_node *np = NULL, *parent;
	int count = 0;

	parent = of_find_node_by_path("/cpus");
	if (!parent) {
		pr_err("failed to find OF /cpus\n");
		return -ENOENT;
		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)) {
			ret = -ENODATA;
		} else {
			of_node_put(np);
			np = NULL;
		}

		break;
	}

	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);
		of_node_put(parent);

	return ret;
}

	return -ENODEV;
}

static int dt_get_transition_latency(struct device *cpu_dev)
{
	struct device_node *np, *parent;
	struct device_node *np;
	u32 transition_latency = CPUFREQ_ETERNAL;
	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");
	np = get_cpu_node_with_valid_op(cpu_dev->id);
	if (!np)
		return CPUFREQ_ETERNAL;
	}

	for_each_child_of_node(parent, np) {
		if (count++ != cpu_dev->id)
			continue;

	of_property_read_u32(np, "clock-latency", &transition_latency);
	of_node_put(np);
		of_node_put(parent);

	pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
	return transition_latency;
}

	pr_info("clock-latency isn't found, use CPUFREQ_ETERNAL transition latency\n");
	return CPUFREQ_ETERNAL;
}

static struct cpufreq_arm_bL_ops dt_bL_ops = {
	.name	= "dt-bl",
	.get_transition_latency = dt_get_transition_latency,
	.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");
Loading