Skip to content

Commit

Permalink
Merge tag 'pm+acpi-3.9-rc2' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/rafael/linux-pm

Pull ACPI and power management fixes from Rafael J Wysocki:

 - Two fixes for the new intel_pstate driver from Dirk Brandewie.

 - Fix for incorrect usage of the .find_bridge() callback from struct
   acpi_bus_type in the USB core and subsequent removal of that callback
   from Rafael J Wysocki.

 - ACPI processor driver cleanups from Chen Gang and Syam Sidhardhan.

 - ACPI initialization and error messages fix from Joe Perches.

 - Operating Performance Points documentation improvement from Nishanth
   Menon.

 - Fixes for memory leaks and potential concurrency issues and sysfs
  attributes leaks during device removal in the core device PM QoS code
  from Rafael J Wysocki.

 - Calxeda Highbank cpufreq driver simplification from Emilio López.

 - cpufreq comment cleanup from Namhyung Kim.

 - Fix for a section mismatch in Calxeda Highbank interprocessor
   communication code from Mark Langsdorf (this is not a PM fix strictly
   speaking, but the code in question went in through the PM tree).

* tag 'pm+acpi-3.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq / intel_pstate: Do not load on VM that does not report max P state.
  cpufreq / intel_pstate: Fix intel_pstate_init() error path
  ACPI / glue: Drop .find_bridge() callback from struct acpi_bus_type
  ACPI / glue: Add .match() callback to struct acpi_bus_type
  ACPI / porocessor: Beautify code, pr->id is u32 which is never < 0
  ACPI / processor: Remove redundant NULL check before kfree
  ACPI / Sleep: Avoid interleaved message on errors
  PM / QoS: Remove device PM QoS sysfs attributes at the right place
  PM / QoS: Fix concurrency issues and memory leaks in device PM QoS
  cpufreq: highbank: do not initialize array with a loop
  PM / OPP: improve introductory documentation
  cpufreq: Fix a typo in comment
  mailbox, pl320-ipc: remove __init from probe function
  • Loading branch information
Linus Torvalds committed Mar 7, 2013
2 parents 19cf3ed + 6bd5165 commit c89b148
Show file tree
Hide file tree
Showing 19 changed files with 215 additions and 214 deletions.
25 changes: 20 additions & 5 deletions Documentation/power/opp.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
*=============*
* OPP Library *
*=============*
Operating Performance Points (OPP) Library
==========================================

(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated

Expand All @@ -16,15 +15,31 @@ Contents

1. Introduction
===============
1.1 What is an Operating Performance Point (OPP)?

Complex SoCs of today consists of a multiple sub-modules working in conjunction.
In an operational system executing varied use cases, not all modules in the SoC
need to function at their highest performing frequency all the time. To
facilitate this, sub-modules in a SoC are grouped into domains, allowing some
domains to run at lower voltage and frequency while other domains are loaded
more. The set of discrete tuples consisting of frequency and voltage pairs that
domains to run at lower voltage and frequency while other domains run at
voltage/frequency pairs that are higher.

The set of discrete tuples consisting of frequency and voltage pairs that
the device will support per domain are called Operating Performance Points or
OPPs.

As an example:
Let us consider an MPU device which supports the following:
{300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V},
{1GHz at minimum voltage of 1.3V}

We can represent these as three OPPs as the following {Hz, uV} tuples:
{300000000, 1000000}
{800000000, 1200000}
{1000000000, 1300000}

1.2 Operating Performance Points Library

OPP library provides a set of helper functions to organize and query the OPP
information. The library is located in drivers/base/power/opp.c and the header
is located in include/linux/opp.h. OPP library can be enabled by enabling
Expand Down
55 changes: 9 additions & 46 deletions drivers/acpi/glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
return -ENODEV;
if (type && type->bus && type->find_device) {
if (type && type->match && type->find_device) {
down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem);
printk(KERN_INFO PREFIX "bus type %s registered\n",
type->bus->name);
printk(KERN_INFO PREFIX "bus type %s registered\n", type->name);
return 0;
}
return -ENODEV;
Expand All @@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem);
list_del_init(&type->list);
up_write(&bus_type_sem);
printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n",
type->bus->name);
printk(KERN_INFO PREFIX "bus type %s unregistered\n",
type->name);
return 0;
}
return -ENODEV;
}
EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);

static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
{
struct acpi_bus_type *tmp, *ret = NULL;

if (!type)
return NULL;

down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) {
if (tmp->bus == type) {
if (tmp->match(dev)) {
ret = tmp;
break;
}
Expand All @@ -82,22 +78,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
return ret;
}

static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
{
struct acpi_bus_type *tmp;
int ret = -ENODEV;

down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) {
if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) {
ret = 0;
break;
}
}
up_read(&bus_type_sem);
return ret;
}

static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
void *addr_p, void **ret_p)
{
Expand Down Expand Up @@ -261,29 +241,12 @@ static int acpi_unbind_one(struct device *dev)

static int acpi_platform_notify(struct device *dev)
{
struct acpi_bus_type *type;
struct acpi_bus_type *type = acpi_get_bus_type(dev);
acpi_handle handle;
int ret;

ret = acpi_bind_one(dev, NULL);
if (ret && (!dev->bus || !dev->parent)) {
/* bridge devices genernally haven't bus or parent */
ret = acpi_find_bridge_device(dev, &handle);
if (!ret) {
ret = acpi_bind_one(dev, handle);
if (ret)
goto out;
}
}

type = acpi_get_bus_type(dev->bus);
if (ret) {
if (!type || !type->find_device) {
DBG("No ACPI bus support for %s\n", dev_name(dev));
ret = -EINVAL;
goto out;
}

if (ret && type) {
ret = type->find_device(dev, &handle);
if (ret) {
DBG("Unable to get handle for %s\n", dev_name(dev));
Expand Down Expand Up @@ -316,7 +279,7 @@ static int acpi_platform_notify_remove(struct device *dev)
{
struct acpi_bus_type *type;

type = acpi_get_bus_type(dev->bus);
type = acpi_get_bus_type(dev);
if (type && type->cleanup)
type->cleanup(dev);

Expand Down
3 changes: 1 addition & 2 deletions drivers/acpi/processor_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,7 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
}

exit:
if (buffer.pointer)
kfree(buffer.pointer);
kfree(buffer.pointer);
return apic_id;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/processor_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return 0;
#endif

BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
BUG_ON(pr->id >= nr_cpu_ids);

/*
* Buggy BIOS check
Expand Down
16 changes: 11 additions & 5 deletions drivers/acpi/sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,6 @@ static void acpi_sleep_suspend_setup(void)
status = acpi_get_sleep_type_data(i, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
sleep_states[i] = 1;
pr_cont(" S%d", i);
}
}

Expand Down Expand Up @@ -742,7 +741,6 @@ static void acpi_sleep_hibernate_setup(void)
hibernation_set_ops(old_suspend_ordering ?
&acpi_hibernation_ops_old : &acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1;
pr_cont(KERN_CONT " S4");
if (nosigcheck)
return;

Expand Down Expand Up @@ -788,26 +786,34 @@ int __init acpi_sleep_init(void)
{
acpi_status status;
u8 type_a, type_b;
char supported[ACPI_S_STATE_COUNT * 3 + 1];
char *pos = supported;
int i;

if (acpi_disabled)
return 0;

acpi_sleep_dmi_check();

sleep_states[ACPI_STATE_S0] = 1;
pr_info(PREFIX "(supports S0");

acpi_sleep_suspend_setup();
acpi_sleep_hibernate_setup();

status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
if (ACPI_SUCCESS(status)) {
sleep_states[ACPI_STATE_S5] = 1;
pr_cont(" S5");
pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off;
}
pr_cont(")\n");

supported[0] = 0;
for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
if (sleep_states[i])
pos += sprintf(pos, " S%d", i);
}
pr_info(PREFIX "(supports%s)\n", supported);

/*
* Register the tts_notifier to reboot notifier list so that the _TTS
* object can also be evaluated when the system enters S5.
Expand Down
7 changes: 1 addition & 6 deletions drivers/ata/libata-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,13 +1144,8 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
return -ENODEV;
}

static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
{
return -ENODEV;
}

static struct acpi_bus_type ata_acpi_bus = {
.find_bridge = ata_acpi_find_dummy,
.name = "ATA",
.find_device = ata_acpi_find_device,
};

Expand Down
2 changes: 0 additions & 2 deletions drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ void device_pm_add(struct device *dev)
dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
dev_pm_qos_constraints_init(dev);
mutex_unlock(&dpm_list_mtx);
}

Expand All @@ -113,7 +112,6 @@ void device_pm_remove(struct device *dev)
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
complete_all(&dev->power.completion);
mutex_lock(&dpm_list_mtx);
dev_pm_qos_constraints_destroy(dev);
list_del_init(&dev->power.entry);
mutex_unlock(&dpm_list_mtx);
device_wakeup_disable(dev);
Expand Down
8 changes: 2 additions & 6 deletions drivers/base/power/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ static inline void device_pm_init_common(struct device *dev)
{
if (!dev->power.early_init) {
spin_lock_init(&dev->power.lock);
dev->power.power_state = PMSG_INVALID;
dev->power.qos = NULL;
dev->power.early_init = true;
}
}
Expand Down Expand Up @@ -56,14 +56,10 @@ extern void device_pm_move_last(struct device *);

static inline void device_pm_sleep_init(struct device *dev) {}

static inline void device_pm_add(struct device *dev)
{
dev_pm_qos_constraints_init(dev);
}
static inline void device_pm_add(struct device *dev) {}

static inline void device_pm_remove(struct device *dev)
{
dev_pm_qos_constraints_destroy(dev);
pm_runtime_remove(dev);
}

Expand Down
Loading

0 comments on commit c89b148

Please sign in to comment.