forked from Minki/linux
Power management fixes for 3.6-rc6
* Three ACPI device power management fixes related to checking and setting device power states. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQIcBAABAgAGBQJQVN5wAAoJEKhOf7ml8uNsUEUQAJN7kQI4x/3BRw+JPXsuQcZ+ HKoAT23eKuPpkuBgfnyacB0NMVB8VVLoYqFq/L282k2mkuO/dJ1NVruAOBikuApH U/bf7Rct2gFI0AkPBAx+itGnNx2xxALd0NbpZLgccKxgmbc5TT5BtzYK9uFSNSuQ y0QzKzGYrlfE7PV1439eQvHn9nffpeJHUoZVJtZlHOPuGlX12SpOEIHnaHnFH1rF XY58zYFPDCE0qaWR9r4i/bcgdcatDP30JHSoULtRDse46En2ebGlyuiGZrbs8HZ1 PzFzjGd3X6vbycX+gpEGuFMzKAyUjFhChZ8DGGlTQ7H3mxDBBtNIDiqIdKw27DUJ LvwpOk8LPAcgkO0zvoUf3Won92HcXS2TPC6/AjosOYXi9n9gZFzCVuKTnvUDcEP3 AI1+MVGELEJowIYkx8Thafcr0ipEsMXMb2GQfnSuotdL6V/pzlMZsaJneMp34W3v P/3CkOj+JEH3K6Ode4AoRQB+pwLBLPBHAN/sNTUtNLDUrkNYmNdDHiam7ZyG6ffh 2Sxrc9N1e3Q0Ogy1h+vMr/ZjUbiPyCl5YlsC+Iasm0AuvioN00IFNMEcSlRzS6X8 HhjNVMUIOoIwU4ZBm3lnTnMh2DnlRtJDH9NHuW9qR/g/7cHn3oiBEGZ5GOrA5Q+L 3QkosGc/V7tMPuA+tZiO =TTmm -----END PGP SIGNATURE----- Merge tag 'pm-for-3.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull power management fixes from Rafael J. Wysocki: "Three ACPI device power management fixes related to checking and setting device power states." * tag 'pm-for-3.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / PM: Use KERN_DEBUG when no power resources are found ACPI / PM: Fix resource_lock dead lock in acpi_power_on_device ACPI / PM: Infer parent power state from child if unknown, v2
This commit is contained in:
commit
9bc67590a6
@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)
|
||||
} else if (result == ACPI_STATE_D3_HOT) {
|
||||
result = ACPI_STATE_D3;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we were unsure about the device parent's power state up to this
|
||||
* point, the fact that the device is in D0 implies that the parent has
|
||||
* to be in D0 too.
|
||||
*/
|
||||
if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN
|
||||
&& result == ACPI_STATE_D0)
|
||||
device->parent->power.state = ACPI_STATE_D0;
|
||||
|
||||
*state = result;
|
||||
|
||||
out:
|
||||
|
@ -107,6 +107,7 @@ struct acpi_power_resource {
|
||||
|
||||
/* List of devices relying on this power resource */
|
||||
struct acpi_power_resource_device *devices;
|
||||
struct mutex devices_lock;
|
||||
};
|
||||
|
||||
static struct list_head acpi_power_resource_list;
|
||||
@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device)
|
||||
|
||||
static int __acpi_power_on(struct acpi_power_resource *resource)
|
||||
{
|
||||
struct acpi_power_resource_device *device_list = resource->devices;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
|
||||
@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
|
||||
resource->name));
|
||||
|
||||
while (device_list) {
|
||||
acpi_power_on_device(device_list->device);
|
||||
|
||||
device_list = device_list->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_power_on(acpi_handle handle)
|
||||
{
|
||||
int result = 0;
|
||||
bool resume_device = false;
|
||||
struct acpi_power_resource *resource = NULL;
|
||||
struct acpi_power_resource_device *device_list;
|
||||
|
||||
result = acpi_power_get_context(handle, &resource);
|
||||
if (result)
|
||||
@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle)
|
||||
result = __acpi_power_on(resource);
|
||||
if (result)
|
||||
resource->ref_count--;
|
||||
else
|
||||
resume_device = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
|
||||
if (!resume_device)
|
||||
return result;
|
||||
|
||||
mutex_lock(&resource->devices_lock);
|
||||
|
||||
device_list = resource->devices;
|
||||
while (device_list) {
|
||||
acpi_power_on_device(device_list->device);
|
||||
device_list = device_list->next;
|
||||
}
|
||||
|
||||
mutex_unlock(&resource->devices_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,
|
||||
if (acpi_power_get_context(res_handle, &resource))
|
||||
return;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
mutex_lock(&resource->devices_lock);
|
||||
prev = NULL;
|
||||
curr = resource->devices;
|
||||
while (curr) {
|
||||
@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
mutex_unlock(&resource->devices_lock);
|
||||
}
|
||||
|
||||
/* Unlink dev from all power resources in _PR0 */
|
||||
@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device(
|
||||
|
||||
power_resource_device->device = powered_device;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
mutex_lock(&resource->devices_lock);
|
||||
power_resource_device->next = resource->devices;
|
||||
resource->devices = power_resource_device;
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
mutex_unlock(&resource->devices_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -462,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
|
||||
return ret;
|
||||
|
||||
no_power_resource:
|
||||
printk(KERN_WARNING PREFIX "Invalid Power Resource to register!");
|
||||
printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
|
||||
@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device)
|
||||
|
||||
resource->device = device;
|
||||
mutex_init(&resource->resource_lock);
|
||||
mutex_init(&resource->devices_lock);
|
||||
strcpy(resource->name, device->pnp.bus_id);
|
||||
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
|
||||
|
Loading…
Reference in New Issue
Block a user