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/pci_root.c | 101 | ||||
-rw-r--r-- | drivers/acpi/pci_slot.c | 44 |
4 files changed, 79 insertions, 146 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/pci_root.c b/drivers/acpi/pci_root.c index 72a2c98..bce469c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -27,7 +27,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> -#include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/pci.h> @@ -71,9 +71,11 @@ static struct acpi_driver acpi_pci_root_driver = { }, }; +/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ +static DEFINE_MUTEX(acpi_pci_root_lock); static LIST_HEAD(acpi_pci_roots); +static LIST_HEAD(acpi_pci_drivers); -static struct acpi_pci_driver *sub_driver; static DEFINE_MUTEX(osc_lock); int acpi_pci_register_driver(struct acpi_pci_driver *driver) @@ -81,55 +83,46 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) int n = 0; struct acpi_pci_root *root; - struct acpi_pci_driver **pptr = &sub_driver; - while (*pptr) - pptr = &(*pptr)->next; - *pptr = driver; - - if (!driver->add) - return 0; - - list_for_each_entry(root, &acpi_pci_roots, node) { - driver->add(root->device->handle); - n++; - } + mutex_lock(&acpi_pci_root_lock); + list_add_tail(&driver->node, &acpi_pci_drivers); + if (driver->add) + list_for_each_entry(root, &acpi_pci_roots, node) { + driver->add(root); + n++; + } + mutex_unlock(&acpi_pci_root_lock); return n; } - EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { struct acpi_pci_root *root; - struct acpi_pci_driver **pptr = &sub_driver; - while (*pptr) { - if (*pptr == driver) - break; - pptr = &(*pptr)->next; - } - BUG_ON(!*pptr); - *pptr = (*pptr)->next; - - if (!driver->remove) - return; - - list_for_each_entry(root, &acpi_pci_roots, node) - driver->remove(root->device->handle); + mutex_lock(&acpi_pci_root_lock); + list_del(&driver->node); + if (driver->remove) + list_for_each_entry(root, &acpi_pci_roots, node) + driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); } - EXPORT_SYMBOL(acpi_pci_unregister_driver); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) { struct acpi_pci_root *root; + acpi_handle handle = NULL; + mutex_lock(&acpi_pci_root_lock); list_for_each_entry(root, &acpi_pci_roots, node) if ((root->segment == (u16) seg) && - (root->secondary.start == (u16) bus)) - return root->device->handle; - return NULL; + (root->secondary.start == (u16) bus)) { + handle = root->device->handle; + break; + } + mutex_unlock(&acpi_pci_root_lock); + return handle; } EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); @@ -277,12 +270,15 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) { struct acpi_pci_root *root; + struct acpi_device *device; - list_for_each_entry(root, &acpi_pci_roots, node) { - if (root->device->handle == handle) - return root; - } - return NULL; + if (acpi_bus_get_device(handle, &device) || + acpi_match_device_ids(device, root_device_ids)) + return NULL; + + root = acpi_driver_data(device); + + return root; } EXPORT_SYMBOL_GPL(acpi_pci_find_root); @@ -518,8 +514,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) * TBD: Need PCI interface for enumeration/configuration of roots. */ - /* TBD: Locking */ + mutex_lock(&acpi_pci_root_lock); list_add_tail(&root->node, &acpi_pci_roots); + mutex_unlock(&acpi_pci_root_lock); printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), @@ -538,7 +535,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) "Bus %04x:%02x not present in PCI namespace\n", root->segment, (unsigned int)root->secondary.start); result = -ENODEV; - goto end; + goto out_del_root; } /* @@ -548,7 +545,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) */ result = acpi_pci_bind_root(device); if (result) - goto end; + goto out_del_root; /* * PCI Routing Table @@ -633,9 +630,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) return 0; +out_del_root: + mutex_lock(&acpi_pci_root_lock); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); end: - if (!list_empty(&root->node)) - list_del(&root->node); kfree(root); return result; } @@ -643,18 +642,34 @@ end: static int acpi_pci_root_start(struct acpi_device *device) { struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_driver *driver; + + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(driver, &acpi_pci_drivers, node) + if (driver->add) + driver->add(root); + mutex_unlock(&acpi_pci_root_lock); pci_bus_add_devices(root->bus); + return 0; } static int acpi_pci_root_remove(struct acpi_device *device, int type) { struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_driver *driver; + + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(driver, &acpi_pci_drivers, node) + if (driver->remove) + driver->remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); kfree(root); return 0; } diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index e50e31a..d22585f 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -67,8 +67,8 @@ struct acpi_pci_slot { struct list_head list; /* node in the list of slots */ }; -static int acpi_pci_slot_add(acpi_handle handle); -static void acpi_pci_slot_remove(acpi_handle handle); +static int acpi_pci_slot_add(struct acpi_pci_root *root); +static void acpi_pci_slot_remove(struct acpi_pci_root *root); static LIST_HEAD(slot_list); static DEFINE_MUTEX(slot_list_lock); @@ -233,45 +233,20 @@ out: /* * walk_root_bridge - generic root bridge walker - * @handle: points to an acpi_pci_root + * @root: poiner of an acpi_pci_root * @user_function: user callback for slot objects * * Call user_function for all objects underneath this root bridge. * Walk p2p bridges underneath us and call user_function on those too. */ static int -walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) +walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function) { - int seg, bus; - unsigned long long tmp; acpi_status status; - acpi_handle dummy_handle; - struct pci_bus *pci_bus; + acpi_handle handle = root->device->handle; + struct pci_bus *pci_bus = root->bus; struct callback_args context; - /* If the bridge doesn't have _STA, we assume it is always there */ - status = acpi_get_handle(handle, "_STA", &dummy_handle); - if (ACPI_SUCCESS(status)) { - status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); - if (ACPI_FAILURE(status)) { - info("%s: _STA evaluation failure\n", __func__); - return 0; - } - if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0) - /* don't register this object */ - return 0; - } - - status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); - seg = ACPI_SUCCESS(status) ? tmp : 0; - - status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); - bus = ACPI_SUCCESS(status) ? tmp : 0; - - pci_bus = pci_find_bus(seg, bus); - if (!pci_bus) - return 0; - context.pci_bus = pci_bus; context.user_function = user_function; context.root_handle = handle; @@ -295,11 +270,11 @@ walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) * @handle: points to an acpi_pci_root */ static int -acpi_pci_slot_add(acpi_handle handle) +acpi_pci_slot_add(struct acpi_pci_root *root) { acpi_status status; - status = walk_root_bridge(handle, register_slot); + status = walk_root_bridge(root, register_slot); if (ACPI_FAILURE(status)) err("%s: register_slot failure - %d\n", __func__, status); @@ -311,10 +286,11 @@ acpi_pci_slot_add(acpi_handle handle) * @handle: points to an acpi_pci_root */ static void -acpi_pci_slot_remove(acpi_handle handle) +acpi_pci_slot_remove(struct acpi_pci_root *root) { struct acpi_pci_slot *slot, *tmp; struct pci_bus *pbus; + acpi_handle handle = root->device->handle; mutex_lock(&slot_list_lock); list_for_each_entry_safe(slot, tmp, &slot_list, list) { |