diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/acpi/bgrt.c | 76 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 10 | ||||
-rw-r--r-- | drivers/acpi/power.c | 36 |
4 files changed, 45 insertions, 81 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8099895..119d58d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD to override that restriction). config ACPI_BGRT - tristate "Boottime Graphics Resource Table support" - default n + bool "Boottime Graphics Resource Table support" + depends on EFI help This driver adds support for exposing the ACPI Boottime Graphics Resource Table, which allows the operating system to obtain diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 6680df3..be60399 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Red Hat, Inc <mjg@redhat.com> + * Copyright 2012 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,20 +12,10 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/sysfs.h> -#include <linux/io.h> -#include <acpi/acpi.h> -#include <acpi/acpi_bus.h> +#include <linux/efi-bgrt.h> -static struct acpi_table_bgrt *bgrt_tab; static struct kobject *bgrt_kobj; -struct bmp_header { - u16 id; - u32 size; -} __attribute ((packed)); - -static struct bmp_header bmp_header; - static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) { @@ -63,18 +54,7 @@ static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); static ssize_t show_image(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { - int size = attr->size; - void __iomem *image = attr->private; - - if (off >= size) { - count = 0; - } else { - if (off + count > size) - count = size - off; - - memcpy_fromio(buf, image+off, count); - } - + memcpy(buf, attr->private + off, count); return count; } @@ -101,45 +81,18 @@ static struct attribute_group bgrt_attribute_group = { static int __init bgrt_init(void) { - acpi_status status; int ret; - void __iomem *bgrt; - if (acpi_disabled) - return -ENODEV; - - status = acpi_get_table("BGRT", 0, - (struct acpi_table_header **)&bgrt_tab); - - if (ACPI_FAILURE(status)) + if (!bgrt_image) return -ENODEV; sysfs_bin_attr_init(&image_attr); - - bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header)); - - if (!bgrt) { - ret = -EINVAL; - goto out_err; - } - - memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header)); - image_attr.size = bmp_header.size; - iounmap(bgrt); - - image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size); - - if (!image_attr.private) { - ret = -EINVAL; - goto out_err; - } - + image_attr.private = bgrt_image; + image_attr.size = bgrt_image_size; bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); - if (!bgrt_kobj) { - ret = -EINVAL; - goto out_iounmap; - } + if (!bgrt_kobj) + return -EINVAL; ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); if (ret) @@ -155,22 +108,11 @@ out_group: sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); out_kobject: kobject_put(bgrt_kobj); -out_iounmap: - iounmap(image_attr.private); -out_err: return ret; } -static void __exit bgrt_exit(void) -{ - iounmap(image_attr.private); - sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); - sysfs_remove_bin_file(bgrt_kobj, &image_attr); -} - module_init(bgrt_init); -module_exit(bgrt_exit); -MODULE_AUTHOR("Matthew Garrett"); +MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>"); MODULE_DESCRIPTION("BGRT boot graphic support"); MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9628652..e059695 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -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: diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index fc18034..40e38a0 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -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); |