diff options
Diffstat (limited to 'drivers/acpi')
215 files changed, 10793 insertions, 7083 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 119d58db8342..92ed9692c47e 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -176,11 +176,16 @@ config ACPI_FAN config ACPI_DOCK bool "Dock" - depends on EXPERIMENTAL help This driver supports ACPI-controlled docking stations and removable drive bays such as the IBM Ultrabay and the Dell Module Bay. +config ACPI_I2C + def_tristate I2C + depends on I2C + help + ACPI I2C enumeration support. + config ACPI_PROCESSOR tristate "Processor" select THERMAL @@ -196,7 +201,7 @@ config ACPI_PROCESSOR the module will be called processor. config ACPI_IPMI tristate "IPMI" - depends on EXPERIMENTAL && IPMI_SI && IPMI_HANDLER + depends on IPMI_SI && IPMI_HANDLER default n help This driver enables the ACPI to access the BMC controller. And it @@ -208,14 +213,13 @@ config ACPI_IPMI config ACPI_HOTPLUG_CPU bool - depends on EXPERIMENTAL && ACPI_PROCESSOR && HOTPLUG_CPU + depends on ACPI_PROCESSOR && HOTPLUG_CPU select ACPI_CONTAINER default y config ACPI_PROCESSOR_AGGREGATOR tristate "Processor Aggregator" depends on ACPI_PROCESSOR - depends on EXPERIMENTAL depends on X86 help ACPI 4.0 defines processor Aggregator, which enables OS to perform @@ -261,6 +265,16 @@ config ACPI_CUSTOM_DSDT bool default ACPI_CUSTOM_DSDT_FILE != "" +config ACPI_INITRD_TABLE_OVERRIDE + bool "ACPI tables override via initrd" + depends on BLK_DEV_INITRD && X86 + default n + help + This option provides functionality to override arbitrary ACPI tables + via initrd. No functional change if no ACPI tables are passed via + initrd, therefore it's safe to say Y. + See Documentation/acpi/initrd_table_override.txt for details + config ACPI_BLACKLIST_YEAR int "Disable ACPI for systems before Jan 1st this year" if X86_32 default 0 @@ -293,7 +307,7 @@ config ACPI_DEBUG_FUNC_TRACE is about half of the penalty and is rarely useful. config ACPI_PCI_SLOT - tristate "PCI slot detection driver" + bool "PCI slot detection driver" depends on SYSFS default n help @@ -302,9 +316,6 @@ config ACPI_PCI_SLOT i.e., segment/bus/device/function tuples, with physical slots in the system. If you are unsure, say N. - To compile this driver as a module, choose M here: - the module will be called pci_slot. - config X86_PM_TIMER bool "Power Management Timer Support" if EXPERT depends on X86 @@ -322,8 +333,7 @@ config X86_PM_TIMER systems require this timer. config ACPI_CONTAINER - tristate "Container and Module Devices (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "Container and Module Devices" default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) help This driver supports ACPI Container and Module devices (IDs diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 82422fe90f81..474fcfeba66c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -21,9 +21,10 @@ obj-y += acpi.o \ acpi-y += osl.o utils.o reboot.o acpi-y += nvs.o -# sleep related files +# Power management related files acpi-y += wakeup.o acpi-y += sleep.o +acpi-$(CONFIG_PM) += device_pm.o acpi-$(CONFIG_ACPI_SLEEP) += proc.o @@ -32,10 +33,13 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o # acpi-y += bus.o glue.o acpi-y += scan.o +acpi-y += resource.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o -acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-y += pci_root.o pci_link.o pci_irq.o +acpi-y += csrt.o +acpi-y += acpi_platform.o acpi-y += power.o acpi-y += event.o acpi-y += sysfs.o @@ -67,6 +71,7 @@ obj-$(CONFIG_ACPI_HED) += hed.o obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o +obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o # processor has its own "processor." module_param namespace processor-y := processor_driver.o processor_throttling.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d5fdd36190cc..6d5bf649196d 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -60,7 +60,7 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file); #endif static int acpi_ac_add(struct acpi_device *device); -static int acpi_ac_remove(struct acpi_device *device, int type); +static int acpi_ac_remove(struct acpi_device *device); static void acpi_ac_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id ac_device_ids[] = { @@ -337,7 +337,7 @@ static int acpi_ac_resume(struct device *dev) } #endif -static int acpi_ac_remove(struct acpi_device *device, int type) +static int acpi_ac_remove(struct acpi_device *device) { struct acpi_ac *ac = NULL; diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c new file mode 100644 index 000000000000..82045e3f5cac --- /dev/null +++ b/drivers/acpi/acpi_i2c.c @@ -0,0 +1,103 @@ +/* + * ACPI I2C enumeration support + * + * Copyright (C) 2012, Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> + * + * 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 + * published by the Free Software Foundation. + */ + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/export.h> +#include <linux/i2c.h> +#include <linux/ioport.h> + +ACPI_MODULE_NAME("i2c"); + +static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) +{ + struct i2c_board_info *info = data; + + if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { + struct acpi_resource_i2c_serialbus *sb; + + sb = &ares->data.i2c_serial_bus; + if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { + info->addr = sb->slave_address; + if (sb->access_mode == ACPI_I2C_10BIT_MODE) + info->flags |= I2C_CLIENT_TEN; + } + } else if (info->irq < 0) { + struct resource r; + + if (acpi_dev_resource_interrupt(ares, 0, &r)) + info->irq = r.start; + } + + /* Tell the ACPI core to skip this resource */ + return 1; +} + +static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, + void *data, void **return_value) +{ + struct i2c_adapter *adapter = data; + struct list_head resource_list; + struct i2c_board_info info; + struct acpi_device *adev; + int ret; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + if (acpi_bus_get_status(adev) || !adev->status.present) + return AE_OK; + + memset(&info, 0, sizeof(info)); + info.acpi_node.handle = handle; + info.irq = -1; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, + acpi_i2c_add_resource, &info); + acpi_dev_free_resource_list(&resource_list); + + if (ret < 0 || !info.addr) + return AE_OK; + + strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); + if (!i2c_new_device(adapter, &info)) { + dev_err(&adapter->dev, + "failed to add I2C device %s from ACPI\n", + dev_name(&adev->dev)); + } + + return AE_OK; +} + +/** + * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter + * @adapter: pointer to adapter + * + * Enumerate all I2C slave devices behind this adapter by walking the ACPI + * namespace. When a device is found it will be added to the Linux device + * model and bound to the corresponding ACPI handle. + */ +void acpi_i2c_register_devices(struct i2c_adapter *adapter) +{ + acpi_handle handle; + acpi_status status; + + handle = ACPI_HANDLE(&adapter->dev); + if (!handle) + return; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + acpi_i2c_add_device, NULL, + adapter, NULL); + if (ACPI_FAILURE(status)) + dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n"); +} +EXPORT_SYMBOL_GPL(acpi_i2c_register_devices); diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 24c807f96636..da1f82b445e0 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -31,6 +31,7 @@ #include <linux/types.h> #include <linux/memory_hotplug.h> #include <linux/slab.h> +#include <linux/acpi.h> #include <acpi/acpi_drivers.h> #define ACPI_MEMORY_DEVICE_CLASS "memory" @@ -53,7 +54,7 @@ MODULE_LICENSE("GPL"); #define MEMORY_POWER_OFF_STATE 2 static int acpi_memory_device_add(struct acpi_device *device); -static int acpi_memory_device_remove(struct acpi_device *device, int type); +static int acpi_memory_device_remove(struct acpi_device *device); static const struct acpi_device_id memory_device_ids[] = { {ACPI_MEMORY_DEVICE_HID, 0}, @@ -78,6 +79,7 @@ struct acpi_memory_info { unsigned short caching; /* memory cache attribute */ unsigned short write_protect; /* memory read/write attribute */ unsigned int enabled:1; + unsigned int failed:1; }; struct acpi_memory_device { @@ -86,8 +88,6 @@ struct acpi_memory_device { struct list_head res_list; }; -static int acpi_hotmem_initialized; - static acpi_status acpi_memory_get_resource(struct acpi_resource *resource, void *context) { @@ -125,12 +125,20 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context) return AE_OK; } +static void +acpi_memory_free_device_resources(struct acpi_memory_device *mem_device) +{ + struct acpi_memory_info *info, *n; + + list_for_each_entry_safe(info, n, &mem_device->res_list, list) + kfree(info); + INIT_LIST_HEAD(&mem_device->res_list); +} + static int acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) { acpi_status status; - struct acpi_memory_info *info, *n; - if (!list_empty(&mem_device->res_list)) return 0; @@ -138,60 +146,53 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, acpi_memory_get_resource, mem_device); if (ACPI_FAILURE(status)) { - list_for_each_entry_safe(info, n, &mem_device->res_list, list) - kfree(info); - INIT_LIST_HEAD(&mem_device->res_list); + acpi_memory_free_device_resources(mem_device); return -EINVAL; } return 0; } -static int -acpi_memory_get_device(acpi_handle handle, - struct acpi_memory_device **mem_device) +static int acpi_memory_get_device(acpi_handle handle, + struct acpi_memory_device **mem_device) { - acpi_status status; - acpi_handle phandle; struct acpi_device *device = NULL; - struct acpi_device *pdevice = NULL; - int result; + int result = 0; + acpi_scan_lock_acquire(); - if (!acpi_bus_get_device(handle, &device) && device) + acpi_bus_get_device(handle, &device); + if (device) goto end; - status = acpi_get_parent(handle, &phandle); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent")); - return -EINVAL; - } - - /* Get the parent device */ - result = acpi_bus_get_device(phandle, &pdevice); - if (result) { - printk(KERN_WARNING PREFIX "Cannot get acpi bus device"); - return -EINVAL; - } - /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + result = acpi_bus_scan(handle); if (result) { - printk(KERN_WARNING PREFIX "Cannot add acpi bus"); - return -EINVAL; + acpi_handle_warn(handle, "ACPI namespace scan failed\n"); + result = -EINVAL; + goto out; + } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + result = -EINVAL; + goto out; } - end: + end: *mem_device = acpi_driver_data(device); if (!(*mem_device)) { - printk(KERN_ERR "\n driver data not found"); - return -ENODEV; + dev_err(&device->dev, "driver data not found\n"); + result = -ENODEV; + goto out; } - return 0; + out: + acpi_scan_lock_release(); + return result; } static int acpi_memory_check_device(struct acpi_memory_device *mem_device) @@ -220,15 +221,6 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) struct acpi_memory_info *info; int node; - - /* Get the range from the _CRS */ - result = acpi_memory_get_device_resources(mem_device); - if (result) { - printk(KERN_ERR PREFIX "get_device_resources failed\n"); - mem_device->state = MEMORY_INVALID_STATE; - return result; - } - node = acpi_get_node(mem_device->device->handle); /* * Tell the VM there is more memory here... @@ -251,13 +243,27 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) node = memory_add_physaddr_to_nid(info->start_addr); result = add_memory(node, info->start_addr, info->length); - if (result) + + /* + * If the memory block has been used by the kernel, add_memory() + * returns -EEXIST. If add_memory() returns the other error, it + * means that this memory block is not used by the kernel. + */ + if (result && result != -EEXIST) { + info->failed = 1; continue; - info->enabled = 1; + } + + if (!result) + info->enabled = 1; + /* + * Add num_enable even if add_memory() returns -EEXIST, so the + * device is bound to this driver. + */ num_enabled++; } if (!num_enabled) { - printk(KERN_ERR PREFIX "add_memory failed\n"); + dev_err(&mem_device->device->dev, "add_memory failed\n"); mem_device->state = MEMORY_INVALID_STATE; return -EINVAL; } @@ -272,68 +278,35 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) return 0; } -static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device) +static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) { - acpi_status status; - struct acpi_object_list arg_list; - union acpi_object arg; - unsigned long long current_status; - - - /* Issue the _EJ0 command */ - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - status = acpi_evaluate_object(mem_device->device->handle, - "_EJ0", &arg_list, NULL); - /* Return on _EJ0 failure */ - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "_EJ0 failed")); - return -ENODEV; - } - - /* Evalute _STA to check if the device is disabled */ - status = acpi_evaluate_integer(mem_device->device->handle, "_STA", - NULL, ¤t_status); - if (ACPI_FAILURE(status)) - return -ENODEV; + int result = 0, nid; + struct acpi_memory_info *info, *n; - /* Check for device status. Device should be disabled */ - if (current_status & ACPI_STA_DEVICE_ENABLED) - return -EINVAL; + nid = acpi_get_node(mem_device->device->handle); - return 0; -} + list_for_each_entry_safe(info, n, &mem_device->res_list, list) { + if (info->failed) + /* The kernel does not use this memory block */ + continue; -static int acpi_memory_disable_device(struct acpi_memory_device *mem_device) -{ - int result; - struct acpi_memory_info *info, *n; + if (!info->enabled) + /* + * The kernel uses this memory block, but it may be not + * managed by us. + */ + return -EBUSY; + if (nid < 0) + nid = memory_add_physaddr_to_nid(info->start_addr); + result = remove_memory(nid, info->start_addr, info->length); + if (result) + return result; - /* - * Ask the VM to offline this memory range. - * Note: Assume that this function returns zero on success - */ - list_for_each_entry_safe(info, n, &mem_device->res_list, list) { - if (info->enabled) { - result = remove_memory(info->start_addr, info->length); - if (result) - return result; - } + list_del(&info->list); kfree(info); } - /* Power-off and eject the device */ - result = acpi_memory_powerdown_device(mem_device); - if (result) { - /* Set the status of the device to invalid */ - mem_device->state = MEMORY_INVALID_STATE; - return result; - } - - mem_device->state = MEMORY_POWER_OFF_STATE; return result; } @@ -341,7 +314,9 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) { struct acpi_memory_device *mem_device; struct acpi_device *device; + struct acpi_eject_event *ej_event = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_status status; switch (event) { case ACPI_NOTIFY_BUS_CHECK: @@ -353,15 +328,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived DEVICE CHECK notification for device\n")); if (acpi_memory_get_device(handle, &mem_device)) { - printk(KERN_ERR PREFIX "Cannot find driver data\n"); - break; - } - - if (acpi_memory_check_device(mem_device)) - break; - - if (acpi_memory_enable_device(mem_device)) { - printk(KERN_ERR PREFIX "Cannot enable memory device\n"); + acpi_handle_err(handle, "Cannot find driver data\n"); break; } @@ -372,41 +339,40 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived EJECT REQUEST notification for device\n")); + status = AE_ERROR; + acpi_scan_lock_acquire(); + if (acpi_bus_get_device(handle, &device)) { - printk(KERN_ERR PREFIX "Device doesn't exist\n"); - break; + acpi_handle_err(handle, "Device doesn't exist\n"); + goto unlock; } mem_device = acpi_driver_data(device); if (!mem_device) { - printk(KERN_ERR PREFIX "Driver Data is NULL\n"); - break; + acpi_handle_err(handle, "Driver Data is NULL\n"); + goto unlock; } - /* - * Currently disabling memory device from kernel mode - * TBD: Can also be disabled from user mode scripts - * TBD: Can also be disabled by Callback registration - * with generic sysfs driver - */ - if (acpi_memory_disable_device(mem_device)) { - printk(KERN_ERR PREFIX "Disable memory device\n"); - /* - * If _EJ0 was called but failed, _OST is not - * necessary. - */ - if (mem_device->state == MEMORY_INVALID_STATE) - return; - - break; + ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); + if (!ej_event) { + pr_err(PREFIX "No memory, dropping EJECT\n"); + goto unlock; } - /* - * TBD: Invoke acpi_bus_remove to cleanup data structures - */ - - /* _EJ0 succeeded; _OST is not necessary */ - return; + get_device(&device->dev); + ej_event->device = device; + ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + /* The eject is carried out asynchronously. */ + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, + ej_event); + if (ACPI_FAILURE(status)) { + put_device(&device->dev); + kfree(ej_event); + } + unlock: + acpi_scan_lock_release(); + if (ACPI_SUCCESS(status)) + return; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); @@ -417,7 +383,15 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - return; +} + +static void acpi_memory_device_free(struct acpi_memory_device *mem_device) +{ + if (!mem_device) + return; + + acpi_memory_free_device_resources(mem_device); + kfree(mem_device); } static int acpi_memory_device_add(struct acpi_device *device) @@ -449,37 +423,35 @@ static int acpi_memory_device_add(struct acpi_device *device) /* Set the device state */ mem_device->state = MEMORY_POWER_ON_STATE; - printk(KERN_DEBUG "%s \n", acpi_device_name(device)); - - /* - * Early boot code has recognized memory area by EFI/E820. - * If DSDT shows these memory devices on boot, hotplug is not necessary - * for them. So, it just returns until completion of this driver's - * start up. - */ - if (!acpi_hotmem_initialized) - return 0; + pr_debug("%s\n", acpi_device_name(device)); if (!acpi_memory_check_device(mem_device)) { /* call add_memory func */ result = acpi_memory_enable_device(mem_device); - if (result) - printk(KERN_ERR PREFIX + if (result) { + dev_err(&device->dev, "Error in acpi_memory_enable_device\n"); + acpi_memory_device_free(mem_device); + } } return result; } -static int acpi_memory_device_remove(struct acpi_device *device, int type) +static int acpi_memory_device_remove(struct acpi_device *device) { struct acpi_memory_device *mem_device = NULL; - + int result; if (!device || !acpi_driver_data(device)) return -EINVAL; mem_device = acpi_driver_data(device); - kfree(mem_device); + + result = acpi_memory_remove_memory(mem_device); + if (result) + return result; + + acpi_memory_device_free(mem_device); return 0; } @@ -568,7 +540,6 @@ static int __init acpi_memory_device_init(void) return -ENODEV; } - acpi_hotmem_initialized = 1; return 0; } diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index af4aad6ee2eb..31de1043eea0 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -286,7 +286,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long num; - if (strict_strtoul(buf, 0, &num)) + if (kstrtoul(buf, 0, &num)) return -EINVAL; if (num < 1 || num >= 100) return -EINVAL; @@ -309,7 +309,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long num; - if (strict_strtoul(buf, 0, &num)) + if (kstrtoul(buf, 0, &num)) return -EINVAL; if (num < 1 || num >= 100) return -EINVAL; @@ -332,7 +332,7 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long num; - if (strict_strtoul(buf, 0, &num)) + if (kstrtoul(buf, 0, &num)) return -EINVAL; mutex_lock(&isolated_cpus_lock); acpi_pad_idle_cpus(num); @@ -457,7 +457,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event, dev_name(&device->dev), event, 0); break; default: - printk(KERN_WARNING "Unsupported event [0x%x]\n", event); + pr_warn("Unsupported event [0x%x]\n", event); break; } } @@ -482,8 +482,7 @@ static int acpi_pad_add(struct acpi_device *device) return 0; } -static int acpi_pad_remove(struct acpi_device *device, - int type) +static int acpi_pad_remove(struct acpi_device *device) { mutex_lock(&isolated_cpus_lock); acpi_pad_idle_cpus(0); diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c new file mode 100644 index 000000000000..26fce4b8a632 --- /dev/null +++ b/drivers/acpi/acpi_platform.c @@ -0,0 +1,164 @@ +/* + * ACPI support for platform bus type. + * + * Copyright (C) 2012, Intel Corporation + * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> + * Mathias Nyman <mathias.nyman@linux.intel.com> + * Rafael J. Wysocki <rafael.j.wysocki@intel.com> + * + * 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 + * published by the Free Software Foundation. + */ + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include "internal.h" + +ACPI_MODULE_NAME("platform"); + +/* Flags for acpi_create_platform_device */ +#define ACPI_PLATFORM_CLK BIT(0) + +/* + * The following ACPI IDs are known to be suitable for representing as + * platform devices. + */ +static const struct acpi_device_id acpi_platform_device_ids[] = { + + { "PNP0D40" }, + + /* Haswell LPSS devices */ + { "INT33C0", ACPI_PLATFORM_CLK }, + { "INT33C1", ACPI_PLATFORM_CLK }, + { "INT33C2", ACPI_PLATFORM_CLK }, + { "INT33C3", ACPI_PLATFORM_CLK }, + { "INT33C4", ACPI_PLATFORM_CLK }, + { "INT33C5", ACPI_PLATFORM_CLK }, + { "INT33C6", ACPI_PLATFORM_CLK }, + { "INT33C7", ACPI_PLATFORM_CLK }, + + { } +}; + +static int acpi_create_platform_clks(struct acpi_device *adev) +{ + static struct platform_device *pdev; + + /* Create Lynxpoint LPSS clocks */ + if (!pdev && !strncmp(acpi_device_hid(adev), "INT33C", 6)) { + pdev = platform_device_register_simple("clk-lpt", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + } + + return 0; +} + +/** + * acpi_create_platform_device - Create platform device for ACPI device node + * @adev: ACPI device node to create a platform device for. + * @id: ACPI device ID used to match @adev. + * + * Check if the given @adev can be represented as a platform device and, if + * that's the case, create and register a platform device, populate its common + * resources and returns a pointer to it. Otherwise, return %NULL. + * + * Name of the platform device will be the same as @adev's. + */ +static int acpi_create_platform_device(struct acpi_device *adev, + const struct acpi_device_id *id) +{ + unsigned long flags = id->driver_data; + struct platform_device *pdev = NULL; + struct acpi_device *acpi_parent; + struct platform_device_info pdevinfo; + struct resource_list_entry *rentry; + struct list_head resource_list; + struct resource *resources; + int count; + + if (flags & ACPI_PLATFORM_CLK) { + int ret = acpi_create_platform_clks(adev); + if (ret) { + dev_err(&adev->dev, "failed to create clocks\n"); + return ret; + } + } + + /* If the ACPI node already has a physical device attached, skip it. */ + if (adev->physical_node_count) + return 0; + + INIT_LIST_HEAD(&resource_list); + count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); + if (count <= 0) + return 0; + + resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL); + if (!resources) { + dev_err(&adev->dev, "No memory for resources\n"); + acpi_dev_free_resource_list(&resource_list); + return -ENOMEM; + } + count = 0; + list_for_each_entry(rentry, &resource_list, node) + resources[count++] = rentry->res; + + acpi_dev_free_resource_list(&resource_list); + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + /* + * If the ACPI node has a parent and that parent has a physical device + * attached to it, that physical device should be the parent of the + * platform device we are about to create. + */ + pdevinfo.parent = NULL; + acpi_parent = adev->parent; + if (acpi_parent) { + struct acpi_device_physical_node *entry; + struct list_head *list; + + mutex_lock(&acpi_parent->physical_node_lock); + list = &acpi_parent->physical_node_list; + if (!list_empty(list)) { + entry = list_first_entry(list, + struct acpi_device_physical_node, + node); + pdevinfo.parent = entry->dev; + } + mutex_unlock(&acpi_parent->physical_node_lock); + } + pdevinfo.name = dev_name(&adev->dev); + pdevinfo.id = -1; + pdevinfo.res = resources; + pdevinfo.num_res = count; + pdevinfo.acpi_node.handle = adev->handle; + pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(pdev)) { + dev_err(&adev->dev, "platform device creation failed: %ld\n", + PTR_ERR(pdev)); + pdev = NULL; + } else { + dev_dbg(&adev->dev, "created platform device %s\n", + dev_name(&pdev->dev)); + } + + kfree(resources); + return 1; +} + +static struct acpi_scan_handler platform_handler = { + .ids = acpi_platform_device_ids, + .attach = acpi_create_platform_device, +}; + +void __init acpi_platform_init(void) +{ + acpi_scan_add_handler(&platform_handler); +} diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 7f1d40797e80..a1b9bf5085a2 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -31,6 +31,7 @@ acpi-y += \ evgpeinit.o \ evgpeutil.o \ evglock.o \ + evhandler.o \ evmisc.o \ evregion.o \ evrgnini.o \ @@ -90,6 +91,7 @@ acpi-y += \ nsobject.o \ nsparse.o \ nspredef.o \ + nsprepkg.o \ nsrepair.o \ nsrepair2.o \ nssearch.o \ @@ -104,7 +106,9 @@ acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o acpi-y += \ psargs.o \ psloop.o \ + psobject.o \ psopcode.o \ + psopinfo.o \ psparse.o \ psscope.o \ pstree.o \ @@ -126,7 +130,7 @@ acpi-y += \ rsutils.o \ rsxface.o -acpi-$(ACPI_FUTURE_USAGE) += rsdump.o +acpi-$(ACPI_FUTURE_USAGE) += rsdump.o rsdumpinfo.o acpi-y += \ tbfadt.o \ @@ -155,9 +159,14 @@ acpi-y += \ utmutex.o \ utobject.o \ utosi.o \ + utownerid.o \ utresrc.o \ utstate.o \ + utstring.o \ utxface.o \ utxfinit.o \ utxferror.o \ utxfmutex.o + +acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o + diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h index 8a7d51bfb3b3..8a6c4a0d22db 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ * * Note: The order of these include files is important. */ +#include <acpi/acconfig.h> /* Global configuration constants */ #include "acmacros.h" /* C macros */ #include "aclocal.h" /* Internal data types */ #include "acobject.h" /* ACPI internal object */ diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 5e8abb07724f..9feba08c29fe 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,17 +44,28 @@ #ifndef __ACDEBUG_H__ #define __ACDEBUG_H__ -#define ACPI_DEBUG_BUFFER_SIZE 4196 +#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */ -struct command_info { +struct acpi_db_command_info { char *name; /* Command Name */ u8 min_args; /* Minimum arguments required */ }; -struct argument_info { +struct acpi_db_command_help { + u8 line_count; /* Number of help lines */ + char *invocation; /* Command Invocation */ + char *description; /* Command Description */ +}; + +struct acpi_db_argument_info { char *name; /* Argument Name */ }; +struct acpi_db_execute_walk { + u32 count; + u32 max_count; +}; + #define PARAM_LIST(pl) pl #define DBTEST_OUTPUT_LEVEL(lvl) if (acpi_gbl_db_opt_verbose) #define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\ @@ -77,59 +88,86 @@ acpi_db_single_step(struct acpi_walk_state *walk_state, /* * dbcmds - debug commands and output routines */ -acpi_status acpi_db_disassemble_method(char *name); +struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string); void acpi_db_display_table_info(char *table_arg); -void acpi_db_unload_acpi_table(char *table_arg, char *instance_arg); +void acpi_db_display_template(char *buffer_arg); -void -acpi_db_set_method_breakpoint(char *location, - struct acpi_walk_state *walk_state, - union acpi_parse_object *op); +void acpi_db_unload_acpi_table(char *name); -void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op); +void acpi_db_send_notify(char *name, u32 value); -void acpi_db_get_bus_info(void); +void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg); -void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op); +acpi_status acpi_db_sleep(char *object_arg); -void acpi_db_dump_namespace(char *start_arg, char *depth_arg); +void acpi_db_display_locks(void); -void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg); +void acpi_db_display_resources(char *object_arg); -void acpi_db_send_notify(char *name, u32 value); +ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void)) -void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg); +void acpi_db_display_handlers(void); + +ACPI_HW_DEPENDENT_RETURN_VOID(void + acpi_db_generate_gpe(char *gpe_arg, + char *block_arg)) + +/* + * dbconvert - miscellaneous conversion routines + */ + acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); + +acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object); acpi_status -acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); +acpi_db_convert_to_object(acpi_object_type type, + char *string, union acpi_object *object); -void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg); +u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info); -acpi_status acpi_db_find_name_in_namespace(char *name_arg); +void acpi_db_dump_pld_buffer(union acpi_object *obj_desc); -void acpi_db_set_scope(char *name); +/* + * dbmethod - control method commands + */ +void +acpi_db_set_method_breakpoint(char *location, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op); -ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_db_sleep(char *object_arg)) +void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op); -void acpi_db_find_references(char *object_arg); +void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg); -void acpi_db_display_locks(void); +acpi_status acpi_db_disassemble_method(char *name); -void acpi_db_display_resources(char *object_arg); +void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op); -ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void)) +void acpi_db_batch_execute(char *count_arg); -void acpi_db_check_integrity(void); +/* + * dbnames - namespace commands + */ +void acpi_db_set_scope(char *name); -ACPI_HW_DEPENDENT_RETURN_VOID(void - acpi_db_generate_gpe(char *gpe_arg, - char *block_arg)) +void acpi_db_dump_namespace(char *start_arg, char *depth_arg); + +void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg); + +acpi_status acpi_db_find_name_in_namespace(char *name_arg); void acpi_db_check_predefined_names(void); -void acpi_db_batch_execute(void); +acpi_status +acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); + +void acpi_db_check_integrity(void); + +void acpi_db_find_references(char *object_arg); + +void acpi_db_get_bus_info(void); /* * dbdisply - debug display commands @@ -161,12 +199,15 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc, /* * dbexec - debugger control method execution */ -void acpi_db_execute(char *name, char **args, u32 flags); +void +acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags); void acpi_db_create_execution_threads(char *num_threads_arg, char *num_loops_arg, char *method_name_arg); +void acpi_db_delete_objects(u32 count, union acpi_object *objects); + #ifdef ACPI_DBG_TRACK_ALLOCATIONS u32 acpi_db_get_cache_info(struct acpi_memory_list *cache); #endif @@ -175,7 +216,8 @@ u32 acpi_db_get_cache_info(struct acpi_memory_list *cache); * dbfileio - Debugger file I/O commands */ acpi_object_type -acpi_db_match_argument(char *user_argument, struct argument_info *arguments); +acpi_db_match_argument(char *user_argument, + struct acpi_db_argument_info *arguments); void acpi_db_close_debug_file(void); @@ -208,6 +250,11 @@ acpi_db_command_dispatch(char *input_buffer, void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context); +acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op); + +char *acpi_db_get_next_token(char *string, + char **next, acpi_object_type * return_type); + /* * dbstats - Generation and display of ACPI table statistics */ diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index 5935ba6707e2..427db72a6302 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -309,10 +309,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state); acpi_status acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state); -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *mth_desc, struct acpi_thread_state - *thread); +struct acpi_walk_state * acpi_ds_create_walk_state(acpi_owner_id owner_id, + union acpi_parse_object + *origin, + union acpi_operand_object + *mth_desc, + struct acpi_thread_state + *thread); acpi_status acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index c0a43b38c6a3..ab0e97710381 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,9 +84,11 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info); acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); +acpi_status +acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); -acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); +acpi_status +acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info); struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number); @@ -156,10 +158,23 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, void *context); /* - * evregion - Address Space handling + * evhandler - Address space handling */ +u8 +acpi_ev_has_default_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id); + acpi_status acpi_ev_install_region_handlers(void); +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context); + +/* + * evregion - Operation region support + */ acpi_status acpi_ev_initialize_op_regions(void); acpi_status @@ -178,12 +193,6 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, u8 acpi_ns_is_locked); acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context); - -acpi_status acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, acpi_adr_space_type space_id); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ce79100fb5eb..ecb49927b817 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,7 +70,7 @@ /* * Enable "slack" in the AML interpreter? Default is FALSE, and the - * interpreter strictly follows the ACPI specification. Setting to TRUE + * interpreter strictly follows the ACPI specification. Setting to TRUE * allows the interpreter to ignore certain errors and/or bad AML constructs. * * Currently, these features are enabled by this flag: @@ -155,26 +155,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE); /***************************************************************************** * - * Debug support - * - ****************************************************************************/ - -/* Procedure nesting level for debug output */ - -extern u32 acpi_gbl_nesting_level; - -ACPI_EXTERN u32 acpi_gpe_count; -ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; - -/* Support for dynamic control method tracing mechanism */ - -ACPI_EXTERN u32 acpi_gbl_original_dbg_level; -ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; -ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; - -/***************************************************************************** - * * ACPI Table globals * ****************************************************************************/ @@ -212,14 +192,6 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; -/* Mutex for _OSI support */ - -ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; - -/* Reader/Writer lock is used for namespace walk and dynamic table unload */ - -ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; - /***************************************************************************** * * Mutual exclusion within ACPICA subsystem @@ -253,21 +225,20 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_pending; ACPI_EXTERN acpi_spinlock acpi_gbl_gpe_lock; /* For GPE data structs and registers */ ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ +/* Mutex for _OSI support */ + +ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex; + +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; + /***************************************************************************** * * Miscellaneous globals * ****************************************************************************/ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - -/* Lists for tracking memory allocations */ - -ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list; -ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; -ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats; -#endif - /* Object caches */ ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache; @@ -281,7 +252,7 @@ ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache; ACPI_EXTERN struct acpi_global_notify_handler acpi_gbl_global_notify[2]; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; -ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; +ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler; ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; @@ -326,6 +297,16 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; #endif +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + +/* Lists for tracking memory allocations */ + +ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list; +ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list; +ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats; +ACPI_EXTERN u8 acpi_gbl_disable_mem_tracking; +#endif + /***************************************************************************** * * Namespace globals @@ -385,25 +366,46 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b; * ****************************************************************************/ -extern struct acpi_fixed_event_info - acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_fixed_event_handler - acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; -ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; -ACPI_EXTERN struct acpi_gpe_block_info -*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; - #if (!ACPI_REDUCED_HARDWARE) ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized; -ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler; +ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; +ACPI_EXTERN struct acpi_gpe_block_info + *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; +ACPI_EXTERN acpi_gbl_event_handler acpi_gbl_global_event_handler; ACPI_EXTERN void *acpi_gbl_global_event_handler_context; +ACPI_EXTERN struct acpi_fixed_event_handler + acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; +extern struct acpi_fixed_event_info + acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; #endif /* !ACPI_REDUCED_HARDWARE */ /***************************************************************************** * - * Debugger globals + * Debug support + * + ****************************************************************************/ + +/* Procedure nesting level for debug output */ + +extern u32 acpi_gbl_nesting_level; + +/* Event counters */ + +ACPI_EXTERN u32 acpi_gpe_count; +ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]; + +/* Support for dynamic control method tracing mechanism */ + +ACPI_EXTERN u32 acpi_gbl_original_dbg_level; +ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; +ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; +ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; + +/***************************************************************************** + * + * Debugger and Disassembler globals * ****************************************************************************/ @@ -411,8 +413,12 @@ ACPI_EXTERN u8 acpi_gbl_db_output_flags; #ifdef ACPI_DISASSEMBLER +u8 ACPI_INIT_GLOBAL(acpi_gbl_ignore_noop_operator, FALSE); + ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; ACPI_EXTERN u8 acpi_gbl_db_opt_verbose; +ACPI_EXTERN struct acpi_external_list *acpi_gbl_external_list; +ACPI_EXTERN struct acpi_external_file *acpi_gbl_external_file_list; #endif #ifdef ACPI_DEBUGGER @@ -424,12 +430,14 @@ extern u8 acpi_gbl_db_terminate_threads; ACPI_EXTERN u8 acpi_gbl_db_opt_tables; ACPI_EXTERN u8 acpi_gbl_db_opt_stats; ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods; +ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support; ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]; -ACPI_EXTERN char acpi_gbl_db_line_buf[80]; -ACPI_EXTERN char acpi_gbl_db_parsed_buf[80]; -ACPI_EXTERN char acpi_gbl_db_scope_buf[40]; -ACPI_EXTERN char acpi_gbl_db_debug_filename[40]; +ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]; +ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]; +ACPI_EXTERN char acpi_gbl_db_scope_buf[80]; +ACPI_EXTERN char acpi_gbl_db_debug_filename[80]; ACPI_EXTERN u8 acpi_gbl_db_output_to_file; ACPI_EXTERN char *acpi_gbl_db_buffer; ACPI_EXTERN char *acpi_gbl_db_filename; diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index d902d31abc6c..6357e932bfd9 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index eb308635da72..8af8c9bdeb35 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -458,7 +458,7 @@ void acpi_ex_reacquire_interpreter(void); void acpi_ex_relinquish_interpreter(void); -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); +u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc); void acpi_ex_acquire_global_lock(u32 rule); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index c816ee675094..805f419086ab 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -189,11 +189,10 @@ struct acpi_namespace_node { #define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ #define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */ -#define ANOBJ_IS_EXTERNAL 0x08 /* i_aSL only: This object created via External() */ -#define ANOBJ_METHOD_NO_RETVAL 0x10 /* i_aSL only: Method has no return value */ -#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* i_aSL only: Method has at least one return value */ -#define ANOBJ_IS_BIT_OFFSET 0x40 /* i_aSL only: Reference is a bit offset */ -#define ANOBJ_IS_REFERENCED 0x80 /* i_aSL only: Object was referenced */ +#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */ +#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */ +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */ +#define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */ /* Internal ACPI table management - master table list */ @@ -262,10 +261,10 @@ struct acpi_create_field_info { }; typedef -acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state); +acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state); /* - * Bitmapped ACPI types. Used internally only + * Bitmapped ACPI types. Used internally only */ #define ACPI_BTYPE_ANY 0x00000000 #define ACPI_BTYPE_INTEGER 0x00000001 @@ -411,11 +410,10 @@ struct acpi_gpe_notify_info { struct acpi_gpe_notify_info *next; }; -struct acpi_gpe_notify_object { - struct acpi_namespace_node *node; - struct acpi_gpe_notify_object *next; -}; - +/* + * GPE dispatch info. At any time, the GPE can have at most one type + * of dispatch - Method, Handler, or Implicit Notify. + */ union acpi_gpe_dispatch_info { struct acpi_namespace_node *method_node; /* Method node for this GPE level */ struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ @@ -486,8 +484,10 @@ struct acpi_gpe_device_info { struct acpi_namespace_node *gpe_device; }; -typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context); +typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info * + gpe_xrupt_info, + struct acpi_gpe_block_info *gpe_block, + void *context); /* Information about each particular fixed event */ @@ -582,7 +582,7 @@ struct acpi_pscope_state { }; /* - * Thread state - one per thread across multiple walk states. Multiple walk + * Thread state - one per thread across multiple walk states. Multiple walk * states are created when there are nested control methods executing. */ struct acpi_thread_state { @@ -645,7 +645,7 @@ union acpi_generic_state { * ****************************************************************************/ -typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state); +typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state); /* Address Range info block */ @@ -677,6 +677,8 @@ struct acpi_opcode_info { u8 type; /* Opcode type */ }; +/* Value associated with the parse object */ + union acpi_parse_value { u64 integer; /* Integer constant (Up to 64 bits) */ u32 size; /* bytelist or field size */ @@ -1023,6 +1025,31 @@ struct acpi_port_info { /***************************************************************************** * + * Disassembler + * + ****************************************************************************/ + +struct acpi_external_list { + char *path; + char *internal_path; + struct acpi_external_list *next; + u32 value; + u16 length; + u8 type; + u8 flags; +}; + +/* Values for Flags field above */ + +#define ACPI_IPATH_ALLOCATED 0x01 + +struct acpi_external_file { + char *path; + struct acpi_external_file *next; +}; + +/***************************************************************************** + * * Debugger * ****************************************************************************/ @@ -1031,6 +1058,7 @@ struct acpi_db_method_info { acpi_handle method; acpi_handle main_thread_gate; acpi_handle thread_complete_gate; + acpi_handle info_gate; acpi_thread_id *threads; u32 num_threads; u32 num_created; @@ -1041,6 +1069,7 @@ struct acpi_db_method_info { u32 num_loops; char pathname[128]; char **args; + acpi_object_type *types; /* * Arguments to be passed to method for the command diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index a7f68c47f517..ed7943b9044f 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,14 +49,18 @@ * get into potential aligment issues -- see the STORE macros below. * Use with care. */ -#define ACPI_GET8(ptr) *ACPI_CAST_PTR (u8, ptr) -#define ACPI_GET16(ptr) *ACPI_CAST_PTR (u16, ptr) -#define ACPI_GET32(ptr) *ACPI_CAST_PTR (u32, ptr) -#define ACPI_GET64(ptr) *ACPI_CAST_PTR (u64, ptr) -#define ACPI_SET8(ptr) *ACPI_CAST_PTR (u8, ptr) -#define ACPI_SET16(ptr) *ACPI_CAST_PTR (u16, ptr) -#define ACPI_SET32(ptr) *ACPI_CAST_PTR (u32, ptr) -#define ACPI_SET64(ptr) *ACPI_CAST_PTR (u64, ptr) +#define ACPI_CAST8(ptr) ACPI_CAST_PTR (u8, (ptr)) +#define ACPI_CAST16(ptr) ACPI_CAST_PTR (u16, (ptr)) +#define ACPI_CAST32(ptr) ACPI_CAST_PTR (u32, (ptr)) +#define ACPI_CAST64(ptr) ACPI_CAST_PTR (u64, (ptr)) +#define ACPI_GET8(ptr) (*ACPI_CAST8 (ptr)) +#define ACPI_GET16(ptr) (*ACPI_CAST16 (ptr)) +#define ACPI_GET32(ptr) (*ACPI_CAST32 (ptr)) +#define ACPI_GET64(ptr) (*ACPI_CAST64 (ptr)) +#define ACPI_SET8(ptr, val) (*ACPI_CAST8 (ptr) = (u8) (val)) +#define ACPI_SET16(ptr, val) (*ACPI_CAST16 (ptr) = (u16) (val)) +#define ACPI_SET32(ptr, val) (*ACPI_CAST32 (ptr) = (u32) (val)) +#define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) /* * printf() format helpers @@ -84,29 +88,29 @@ /* These macros reverse the bytes during the move, converting little-endian to big endian */ - /* Big Endian <== Little Endian */ - /* Hi...Lo Lo...Hi */ + /* Big Endian <== Little Endian */ + /* Hi...Lo Lo...Hi */ /* 16-bit source, 16/32/64 destination */ #define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\ - ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ - ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} + ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\ + ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];} /* 32-bit source, 16/32/64 destination */ #define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */ #define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\ - (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ - (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ - (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} + (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\ + (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\ + (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];} #define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\ ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\ @@ -196,24 +200,12 @@ #endif #endif -/* Macros based on machine integer width */ - -#if ACPI_MACHINE_WIDTH == 32 -#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_32_TO_16(d, s) - -#elif ACPI_MACHINE_WIDTH == 64 -#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_64_TO_16(d, s) - -#else -#error unknown ACPI_MACHINE_WIDTH -#endif - /* * Fast power-of-two math macros for non-optimized compilers */ -#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2))) -#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2))) -#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1))) +#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2))) +#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2))) +#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1))) #define ACPI_DIV_2(a) _ACPI_DIV(a, 1) #define ACPI_MUL_2(a) _ACPI_MUL(a, 1) @@ -238,12 +230,12 @@ /* * Rounding macros (Power of two boundaries only) */ -#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \ - (~(((acpi_size) boundary)-1))) +#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \ + (~(((acpi_size) boundary)-1))) -#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \ - (((acpi_size) boundary)-1)) & \ - (~(((acpi_size) boundary)-1))) +#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \ + (((acpi_size) boundary)-1)) & \ + (~(((acpi_size) boundary)-1))) /* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */ @@ -264,7 +256,7 @@ #define ACPI_ROUND_UP_TO(value, boundary) (((value) + ((boundary)-1)) / (boundary)) -#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1)) +#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1)) /* * Bitmask creation @@ -305,6 +297,26 @@ #define ACPI_16BIT_MASK 0x0000FFFF #define ACPI_24BIT_MASK 0x00FFFFFF +/* Macros to extract flag bits from position zero */ + +#define ACPI_GET_1BIT_FLAG(value) ((value) & ACPI_1BIT_MASK) +#define ACPI_GET_2BIT_FLAG(value) ((value) & ACPI_2BIT_MASK) +#define ACPI_GET_3BIT_FLAG(value) ((value) & ACPI_3BIT_MASK) +#define ACPI_GET_4BIT_FLAG(value) ((value) & ACPI_4BIT_MASK) + +/* Macros to extract flag bits from position one and above */ + +#define ACPI_EXTRACT_1BIT_FLAG(field, position) (ACPI_GET_1BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_2BIT_FLAG(field, position) (ACPI_GET_2BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_3BIT_FLAG(field, position) (ACPI_GET_3BIT_FLAG ((field) >> position)) +#define ACPI_EXTRACT_4BIT_FLAG(field, position) (ACPI_GET_4BIT_FLAG ((field) >> position)) + +/* ACPI Pathname helpers */ + +#define ACPI_IS_ROOT_PREFIX(c) ((c) == (u8) 0x5C) /* Backslash */ +#define ACPI_IS_PARENT_PREFIX(c) ((c) == (u8) 0x5E) /* Carat */ +#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (u8) 0x2E) /* Period (dot) */ + /* * An object of type struct acpi_namespace_node can appear in some contexts * where a pointer to an object of type union acpi_operand_object can also @@ -355,7 +367,6 @@ * Ascii error messages can be configured out */ #ifndef ACPI_NO_ERROR_MESSAGES - /* * Error reporting. Callers module and line number are inserted by AE_INFO, * the plist contains a set of parens to allow variable-length lists. @@ -375,169 +386,7 @@ #define ACPI_WARN_PREDEFINED(plist) #define ACPI_INFO_PREDEFINED(plist) -#endif /* ACPI_NO_ERROR_MESSAGES */ - -/* - * Debug macros that are conditionally compiled - */ -#ifdef ACPI_DEBUG_OUTPUT - -/* - * Function entry tracing - */ -#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE - -#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace(ACPI_DEBUG_PARAMETERS) -#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS, (void *)b) -#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS, (u32)b) -#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \ - acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS, (char *)b) - -#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr() - -/* - * Function exit tracing. - * WARNING: These macros include a return statement. This is usually considered - * bad form, but having a separate exit macro is very ugly and difficult to maintain. - * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros - * so that "_AcpiFunctionName" is defined. - * - * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining - * about these constructs. - */ -#ifdef ACPI_USE_DO_WHILE_0 -#define ACPI_DO_WHILE0(a) do a while(0) -#else -#define ACPI_DO_WHILE0(a) a -#endif - -#define return_VOID ACPI_DO_WHILE0 ({ \ - acpi_ut_exit (ACPI_DEBUG_PARAMETERS); \ - return;}) -/* - * There are two versions of most of the return macros. The default version is - * safer, since it avoids side-effects by guaranteeing that the argument will - * not be evaluated twice. - * - * A less-safe version of the macros is provided for optional use if the - * compiler uses excessive CPU stack (for example, this may happen in the - * debug case if code optimzation is disabled.) - */ -#ifndef ACPI_SIMPLE_RETURN_MACROS - -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ - register acpi_status _s = (s); \ - acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, _s); \ - return (_s); }) -#define return_PTR(s) ACPI_DO_WHILE0 ({ \ - register void *_s = (void *) (s); \ - acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) _s); \ - return (_s); }) -#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ - register u64 _s = (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, _s); \ - return (_s); }) -#define return_UINT8(s) ACPI_DO_WHILE0 ({ \ - register u8 _s = (u8) (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) _s); \ - return (_s); }) -#define return_UINT32(s) ACPI_DO_WHILE0 ({ \ - register u32 _s = (u32) (s); \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) _s); \ - return (_s); }) -#else /* Use original less-safe macros */ - -#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_status_exit (ACPI_DEBUG_PARAMETERS, (s)); \ - return((s)); }) -#define return_PTR(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_ptr_exit (ACPI_DEBUG_PARAMETERS, (u8 *) (s)); \ - return((s)); }) -#define return_VALUE(s) ACPI_DO_WHILE0 ({ \ - acpi_ut_value_exit (ACPI_DEBUG_PARAMETERS, (u64) (s)); \ - return((s)); }) -#define return_UINT8(s) return_VALUE(s) -#define return_UINT32(s) return_VALUE(s) - -#endif /* ACPI_SIMPLE_RETURN_MACROS */ - -#else /* !CONFIG_ACPI_DEBUG_FUNC_TRACE */ - -#define ACPI_FUNCTION_TRACE(a) -#define ACPI_FUNCTION_TRACE_PTR(a,b) -#define ACPI_FUNCTION_TRACE_U32(a,b) -#define ACPI_FUNCTION_TRACE_STR(a,b) -#define ACPI_FUNCTION_EXIT -#define ACPI_FUNCTION_STATUS_EXIT(s) -#define ACPI_FUNCTION_VALUE_EXIT(s) -#define ACPI_FUNCTION_TRACE(a) -#define ACPI_FUNCTION_ENTRY() - -#define return_VOID return -#define return_ACPI_STATUS(s) return(s) -#define return_VALUE(s) return(s) -#define return_UINT8(s) return(s) -#define return_UINT32(s) return(s) -#define return_PTR(s) return(s) - -#endif /* CONFIG_ACPI_DEBUG_FUNC_TRACE */ - -/* Conditional execution */ - -#define ACPI_DEBUG_EXEC(a) a -#define ACPI_NORMAL_EXEC(a) - -#define ACPI_DEBUG_DEFINE(a) a; -#define ACPI_DEBUG_ONLY_MEMBERS(a) a; -#define _VERBOSE_STRUCTURES - -/* Stack and buffer dumping */ - -#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a), 0) -#define ACPI_DUMP_OPERANDS(a, b, c) acpi_ex_dump_operands(a, b, c) - -#define ACPI_DUMP_ENTRY(a, b) acpi_ns_dump_entry (a, b) -#define ACPI_DUMP_PATHNAME(a, b, c, d) acpi_ns_dump_pathname(a, b, c, d) -#define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a) -#define ACPI_DUMP_BUFFER(a, b) acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) - -#else -/* - * This is the non-debug case -- make everything go away, - * leaving no executable debug code! - */ -#define ACPI_DEBUG_EXEC(a) -#define ACPI_NORMAL_EXEC(a) a; - -#define ACPI_DEBUG_DEFINE(a) do { } while(0) -#define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0) -#define ACPI_FUNCTION_TRACE(a) do { } while(0) -#define ACPI_FUNCTION_TRACE_PTR(a, b) do { } while(0) -#define ACPI_FUNCTION_TRACE_U32(a, b) do { } while(0) -#define ACPI_FUNCTION_TRACE_STR(a, b) do { } while(0) -#define ACPI_FUNCTION_EXIT do { } while(0) -#define ACPI_FUNCTION_STATUS_EXIT(s) do { } while(0) -#define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0) -#define ACPI_FUNCTION_ENTRY() do { } while(0) -#define ACPI_DUMP_STACK_ENTRY(a) do { } while(0) -#define ACPI_DUMP_OPERANDS(a, b, c) do { } while(0) -#define ACPI_DUMP_ENTRY(a, b) do { } while(0) -#define ACPI_DUMP_TABLES(a, b) do { } while(0) -#define ACPI_DUMP_PATHNAME(a, b, c, d) do { } while(0) -#define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0) -#define ACPI_DUMP_BUFFER(a, b) do { } while(0) - -#define return_VOID return -#define return_ACPI_STATUS(s) return(s) -#define return_VALUE(s) return(s) -#define return_UINT8(s) return(s) -#define return_UINT32(s) return(s) -#define return_PTR(s) return(s) - -#endif /* ACPI_DEBUG_OUTPUT */ +#endif /* ACPI_NO_ERROR_MESSAGES */ #if (!ACPI_REDUCED_HARDWARE) #define ACPI_HW_OPTIONAL_FUNCTION(addr) addr @@ -556,18 +405,6 @@ #define ACPI_DEBUGGER_EXEC(a) #endif -#ifdef ACPI_DEBUG_OUTPUT -/* - * 1) Set name to blanks - * 2) Copy the object name - */ -#define ACPI_ADD_OBJECT_NAME(a,b) ACPI_MEMSET (a->common.name, ' ', sizeof (a->common.name));\ - ACPI_STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name)) -#else - -#define ACPI_ADD_OBJECT_NAME(a,b) -#endif - /* * Memory allocation tracking (DEBUG ONLY) */ @@ -578,13 +415,13 @@ /* Memory allocation */ #ifndef ACPI_ALLOCATE -#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS) #endif #ifndef ACPI_ALLOCATE_ZEROED -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS) #endif #ifndef ACPI_FREE -#define ACPI_FREE(a) acpio_os_free(a) +#define ACPI_FREE(a) acpi_os_free(a) #endif #define ACPI_MEM_TRACKING(a) @@ -592,16 +429,25 @@ /* Memory allocation */ -#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS) -#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS) +#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS) #define ACPI_FREE(a) acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS) #define ACPI_MEM_TRACKING(a) a #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ -/* Preemption point */ -#ifndef ACPI_PREEMPTION_POINT -#define ACPI_PREEMPTION_POINT() /* no preemption */ -#endif +/* + * Macros used for ACPICA utilities only + */ + +/* Generate a UUID */ + +#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ + (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \ + (b) & 0xFF, ((b) >> 8) & 0xFF, \ + (c) & 0xFF, ((c) >> 8) & 0xFF, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) + +#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7')) #endif /* ACMACROS_H */ diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 9b19d4b86424..02cd5482ff8b 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -218,6 +218,18 @@ acpi_ns_check_parameter_count(char *pathname, u32 user_param_count, const union acpi_predefined_info *info); +acpi_status +acpi_ns_check_object_type(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr, + u32 expected_btypes, u32 package_index); + +/* + * nsprepkg - Validation of predefined name packages + */ +acpi_status +acpi_ns_check_package(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr); + /* * nsnames - Name and Scope manipulation */ @@ -333,8 +345,6 @@ acpi_ns_install_node(struct acpi_walk_state *walk_state, /* * nsutils - Utility functions */ -u8 acpi_ns_valid_root_prefix(char prefix); - acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node); u32 acpi_ns_local(acpi_object_type type); diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 364a1303fb8f..cc7ab6dd724e 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -1,4 +1,3 @@ - /****************************************************************************** * * Name: acobject.h - Definition of union acpi_operand_object (Internal object only) @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -179,7 +178,7 @@ struct acpi_object_method { union acpi_operand_object *mutex; u8 *aml_start; union { - ACPI_INTERNAL_METHOD implementation; + acpi_internal_method implementation; union acpi_operand_object *handler; } dispatch; @@ -198,7 +197,7 @@ struct acpi_object_method { /****************************************************************************** * - * Objects that can be notified. All share a common notify_info area. + * Objects that can be notified. All share a common notify_info area. * *****************************************************************************/ @@ -235,7 +234,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; /****************************************************************************** * - * Fields. All share a common header/info field. + * Fields. All share a common header/info field. * *****************************************************************************/ @@ -308,7 +307,7 @@ struct acpi_object_addr_handler { struct acpi_namespace_node *node; /* Parent device */ void *context; acpi_adr_space_setup setup; - union acpi_operand_object *region_list; /* regions using this handler */ + union acpi_operand_object *region_list; /* Regions using this handler */ union acpi_operand_object *next; }; diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index 9440d053fbb3..3fc9ca7e8aa3 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ #define _UNK 0x6B /* - * Reserved ASCII characters. Do not use any of these for + * Reserved ASCII characters. Do not use any of these for * internal opcodes, since they are used to differentiate * name strings from AML opcodes */ @@ -63,7 +63,7 @@ #define _PFX 0x6D /* - * All AML opcodes and the parse-time arguments for each. Used by the AML + * All AML opcodes and the parse-time arguments for each. Used by the AML * parser Each list is compressed into a 32-bit number and stored in the * master opcode table (in psopcode.c). */ @@ -193,7 +193,7 @@ #define ARGP_ZERO_OP ARG_NONE /* - * All AML opcodes and the runtime arguments for each. Used by the AML + * All AML opcodes and the runtime arguments for each. Used by the AML * interpreter Each list is compressed into a 32-bit number and stored * in the master opcode table (in psopcode.c). * diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index b725d780d34d..aed319318835 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -105,7 +105,28 @@ union acpi_parse_object *acpi_ps_find_name(union acpi_parse_object *scope, union acpi_parse_object *acpi_ps_get_parent(union acpi_parse_object *op); /* - * psopcode - AML Opcode information + * psobject - support for parse object processing + */ +acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op); + +acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, union acpi_parse_object **new_op); + +acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status); + +acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status); + +/* + * psopinfo - AML Opcode information */ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); @@ -150,8 +171,7 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state); void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, - union acpi_parse_object **op, - u32 * arg_list, u32 * arg_count); + union acpi_parse_object **op, u32 *arg_list, u32 *arg_count); acpi_status acpi_ps_push_scope(struct acpi_parse_state *parser_state, @@ -212,8 +232,6 @@ void acpi_ps_free_op(union acpi_parse_object *op); u8 acpi_ps_is_leading_char(u32 c); -u8 acpi_ps_is_prefix_char(u32 c); - #ifdef ACPI_FUTURE_USAGE u32 acpi_ps_get_name(union acpi_parse_object *op); #endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 3080c017f5ba..752cc40cdc1e 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -1,12 +1,11 @@ /****************************************************************************** * * Name: acpredef - Information table for ACPI predefined methods and objects - * $Revision: 1.1 $ * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,13 +50,13 @@ * * 1) PTYPE1 packages do not contain sub-packages. * - * ACPI_PTYPE1_FIXED: Fixed length, 1 or 2 object types: + * ACPI_PTYPE1_FIXED: Fixed-length length, 1 or 2 object types: * object type * count * object type * count * - * ACPI_PTYPE1_VAR: Variable length: + * ACPI_PTYPE1_VAR: Variable-length length: * object type (Int/Buf/Ref) * * ACPI_PTYPE1_OPTION: Package has some required and some optional elements @@ -85,10 +84,10 @@ * count * (Used for _CST) * - * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length + * ACPI_PTYPE2_FIXED: Each subpackage is of Fixed-length * (Used for _PRT) * - * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length + * ACPI_PTYPE2_MIN: Each subpackage has a Variable-length but minimum length * (Used for _HPX) * * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length @@ -124,7 +123,8 @@ enum acpi_return_package_types { * These are the names that can actually be evaluated via acpi_evaluate_object. * Not present in this table are the following: * - * 1) Predefined/Reserved names that are never evaluated via acpi_evaluate_object: + * 1) Predefined/Reserved names that are never evaluated via + * acpi_evaluate_object: * _Lxx and _Exx GPE methods * _Qxx EC methods * _T_x compiler temporary variables @@ -149,9 +149,10 @@ enum acpi_return_package_types { * information about the expected structure of the package. This information * is saved here (rather than in a separate table) in order to minimize the * overall size of the stored data. + * + * Note: The additional braces are intended to promote portability. */ -static const union acpi_predefined_info predefined_names[] = -{ +static const union acpi_predefined_info predefined_names[] = { {{"_AC0", 0, ACPI_RTYPE_INTEGER}}, {{"_AC1", 0, ACPI_RTYPE_INTEGER}}, {{"_AC2", 0, ACPI_RTYPE_INTEGER}}, @@ -213,9 +214,8 @@ static const union acpi_predefined_info predefined_names[] = {{"_BCT", 1, ACPI_RTYPE_INTEGER}}, {{"_BDN", 0, ACPI_RTYPE_INTEGER}}, {{"_BFS", 1, 0}}, - {{"_BIF", 0, ACPI_RTYPE_PACKAGE} }, /* Fixed-length (9 Int),(4 Str/Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, - ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER}, 4, 0} }, + {{"_BIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (9 Int),(4 Str) */ + {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING}, 4, 0}}, {{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4, @@ -237,7 +237,8 @@ static const union acpi_predefined_info predefined_names[] = {{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */ {{"_CDM", 0, ACPI_RTYPE_INTEGER}}, {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}}, + {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0, 0}, 0, + 0}}, {{"_CLS", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}}, @@ -252,7 +253,8 @@ static const union acpi_predefined_info predefined_names[] = {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ - {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}}, + {{{ACPI_PTYPE2_PKG_COUNT, ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3, + 0}}, {{"_CWS", 1, ACPI_RTYPE_INTEGER}}, {{"_DCK", 1, ACPI_RTYPE_INTEGER}}, @@ -343,8 +345,8 @@ static const union acpi_predefined_info predefined_names[] = {{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0}, 0, 0}}, - {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}}, + {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Str/1 Buf) */ + {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, ACPI_RTYPE_BUFFER}, 1, 0}}, {{"_MSG", 1, 0}}, {{"_MSM", 4, ACPI_RTYPE_INTEGER}}, @@ -538,7 +540,8 @@ static const union acpi_predefined_info predefined_names[] = /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ - {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, + {{"_WAK", 1, + ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */ /* _WDG/_WED are MS extensions defined by "Windows Instrumentation" */ @@ -551,11 +554,12 @@ static const union acpi_predefined_info predefined_names[] = }; #if 0 + /* This is an internally implemented control method, no need to check */ - {{"_OSI", 1, ACPI_RTYPE_INTEGER}}, +{ { +"_OSI", 1, ACPI_RTYPE_INTEGER}}, /* TBD: */ - _PRT - currently ignore reversed entries. attempt to fix here? think about possibly fixing package elements like _BIF, etc. #endif diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index 0347d0993497..f691d0e4d9fa 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -347,18 +347,21 @@ extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[]; extern struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[]; /* - * rsdump + * rsdumpinfo */ extern struct acpi_rsdump_info acpi_rs_dump_irq[]; +extern struct acpi_rsdump_info acpi_rs_dump_prt[]; extern struct acpi_rsdump_info acpi_rs_dump_dma[]; extern struct acpi_rsdump_info acpi_rs_dump_start_dpf[]; extern struct acpi_rsdump_info acpi_rs_dump_end_dpf[]; extern struct acpi_rsdump_info acpi_rs_dump_io[]; +extern struct acpi_rsdump_info acpi_rs_dump_io_flags[]; extern struct acpi_rsdump_info acpi_rs_dump_fixed_io[]; extern struct acpi_rsdump_info acpi_rs_dump_vendor[]; extern struct acpi_rsdump_info acpi_rs_dump_end_tag[]; extern struct acpi_rsdump_info acpi_rs_dump_memory24[]; extern struct acpi_rsdump_info acpi_rs_dump_memory32[]; +extern struct acpi_rsdump_info acpi_rs_dump_memory_flags[]; extern struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[]; extern struct acpi_rsdump_info acpi_rs_dump_address16[]; extern struct acpi_rsdump_info acpi_rs_dump_address32[]; @@ -372,6 +375,7 @@ extern struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[]; extern struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[]; +extern struct acpi_rsdump_info acpi_rs_dump_general_flags[]; #endif #endif /* __ACRESRC_H__ */ diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index f196e2c9a71f..7896d85876ca 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ****************************************************************************/ /* - * Walk state - current state of a parse tree walk. Used for both a leisurely + * Walk state - current state of a parse tree walk. Used for both a leisurely * stroll through the tree (for whatever reason), and for control method * execution. */ diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 6712965ba8ae..7755e915a007 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 5035327ebccc..0082fa0a6139 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,6 +69,22 @@ extern const char *acpi_gbl_siz_decode[]; extern const char *acpi_gbl_trs_decode[]; extern const char *acpi_gbl_ttp_decode[]; extern const char *acpi_gbl_typ_decode[]; +extern const char *acpi_gbl_ppc_decode[]; +extern const char *acpi_gbl_ior_decode[]; +extern const char *acpi_gbl_dts_decode[]; +extern const char *acpi_gbl_ct_decode[]; +extern const char *acpi_gbl_sbt_decode[]; +extern const char *acpi_gbl_am_decode[]; +extern const char *acpi_gbl_sm_decode[]; +extern const char *acpi_gbl_wm_decode[]; +extern const char *acpi_gbl_cph_decode[]; +extern const char *acpi_gbl_cpo_decode[]; +extern const char *acpi_gbl_dp_decode[]; +extern const char *acpi_gbl_ed_decode[]; +extern const char *acpi_gbl_bpb_decode[]; +extern const char *acpi_gbl_sb_decode[]; +extern const char *acpi_gbl_fc_decode[]; +extern const char *acpi_gbl_pt_decode[]; #endif /* Types for Resource descriptor entries */ @@ -79,14 +95,14 @@ extern const char *acpi_gbl_typ_decode[]; #define ACPI_SMALL_VARIABLE_LENGTH 3 typedef -acpi_status(*acpi_walk_aml_callback) (u8 * aml, +acpi_status(*acpi_walk_aml_callback) (u8 *aml, u32 length, u32 offset, u8 resource_index, void **context); typedef acpi_status(*acpi_pkg_callback) (u8 object_type, - union acpi_operand_object * source_object, + union acpi_operand_object *source_object, union acpi_generic_state * state, void *context); @@ -202,7 +218,9 @@ extern const u8 _acpi_ctype[]; #define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) #define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) -#endif /* ACPI_USE_SYSTEM_CLIBRARY */ +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ + +#define ACPI_IS_ASCII(c) ((c) < 0x80) /* * utcopy - Object construction and conversion interfaces @@ -210,11 +228,11 @@ extern const u8 _acpi_ctype[]; acpi_status acpi_ut_build_simple_object(union acpi_operand_object *obj, union acpi_object *user_obj, - u8 * data_space, u32 * buffer_space_used); + u8 *data_space, u32 *buffer_space_used); acpi_status acpi_ut_build_package_object(union acpi_operand_object *obj, - u8 * buffer, u32 * space_used); + u8 *buffer, u32 *space_used); acpi_status acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj, @@ -287,9 +305,10 @@ acpi_ut_ptr_exit(u32 line_number, const char *function_name, const char *module_name, u32 component_id, u8 *ptr); -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id); +void +acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id); -void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display); +void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset); void acpi_ut_report_error(char *module_name, u32 line_number); @@ -337,15 +356,19 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, */ acpi_status acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id); + struct acpi_pnp_device_id ** return_id); acpi_status acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id); + struct acpi_pnp_device_id ** return_id); + +acpi_status +acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, + struct acpi_pnp_device_id **return_id); acpi_status acpi_ut_execute_CID(struct acpi_namespace_node *device_node, - struct acpica_device_id_list **return_cid_list); + struct acpi_pnp_device_id_list ** return_cid_list); /* * utlock - reader/writer locks @@ -460,35 +483,17 @@ acpi_ut_short_divide(u64 in_dividend, /* * utmisc */ -void ut_convert_backslashes(char *pathname); - const char *acpi_ut_validate_exception(acpi_status status); u8 acpi_ut_is_pci_root_bridge(char *id); u8 acpi_ut_is_aml_table(struct acpi_table_header *table); -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id); - acpi_status acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void *target_object, acpi_pkg_callback walk_callback, void *context); -void acpi_ut_strupr(char *src_string); - -void acpi_ut_print_string(char *string, u8 max_length); - -u8 acpi_ut_valid_acpi_name(u32 name); - -acpi_name acpi_ut_repair_name(char *name); - -u8 acpi_ut_valid_acpi_char(char character, u32 position); - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer); - /* Values for Base above (16=Hex, 10=Decimal) */ #define ACPI_ANY_BASE 0 @@ -505,15 +510,25 @@ acpi_ut_display_init_pathname(u8 type, #endif /* + * utownerid - Support for Table/Method Owner IDs + */ +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id); + +/* * utresrc */ acpi_status -acpi_ut_walk_aml_resources(u8 * aml, +acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, + u8 *aml, acpi_size aml_length, acpi_walk_aml_callback user_function, void **context); -acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index); +acpi_status +acpi_ut_validate_resource(struct acpi_walk_state *walk_state, + void *aml, u8 *return_index); u32 acpi_ut_get_descriptor_length(void *aml); @@ -524,8 +539,28 @@ u8 acpi_ut_get_resource_header_length(void *aml); u8 acpi_ut_get_resource_type(void *aml); acpi_status -acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, - u8 ** end_tag); +acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag); + +/* + * utstring - String and character utilities + */ +void acpi_ut_strupr(char *src_string); + +void acpi_ut_strlwr(char *src_string); + +int acpi_ut_stricmp(char *string1, char *string2); + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); + +void acpi_ut_print_string(char *string, u8 max_length); + +void ut_convert_backslashes(char *pathname); + +u8 acpi_ut_valid_acpi_name(u32 name); + +u8 acpi_ut_valid_acpi_char(char character, u32 position); + +void acpi_ut_repair_name(char *name); /* * utmutex - mutex support diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index c26f8ff6c3b9..48a3e331b72d 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index af4947956ec2..87c26366d1df 100644 --- a/drivers/acpi/acpica/amlresrc.h +++ b/drivers/acpi/acpica/amlresrc.h @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: amlresrc.h - AML resource descriptors @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -200,6 +199,12 @@ struct aml_resource_fixed_dma { struct aml_resource_large_header { AML_RESOURCE_LARGE_HEADER_COMMON}; +/* General Flags for address space resource descriptors */ + +#define ACPI_RESOURCE_FLAG_DEC 2 +#define ACPI_RESOURCE_FLAG_MIF 4 +#define ACPI_RESOURCE_FLAG_MAF 8 + struct aml_resource_memory24 { AML_RESOURCE_LARGE_HEADER_COMMON u8 flags; u16 minimum; diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index c8b5e2565b98..fb09b08d7080 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index 465f02134b89..7ea0f162f11c 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -280,7 +280,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, /* * Get the return value and save as the last result - * value. This is the only place where walk_state->return_desc + * value. This is the only place where walk_state->return_desc * is set to anything other than zero! */ walk_state->return_desc = walk_state->operands[0]; diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 3da6fd8530c5..feadeed1012d 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -277,7 +277,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, * * RETURN: Status * - * DESCRIPTION: Process all named fields in a field declaration. Names are + * DESCRIPTION: Process all named fields in a field declaration. Names are * entered into the namespace. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 87eff701ecfa..bc8e63f7784b 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index aa9a5d4e4052..a9ffd44c18fe 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ #include "acinterp.h" #include "acnamesp.h" #ifdef ACPI_DISASSEMBLER -#include <acpi/acdisasm.h> +#include "acdisasm.h" #endif #define _COMPONENT ACPI_DISPATCHER @@ -151,6 +151,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { + acpi_ut_delete_object_desc(mutex_desc); return_ACPI_STATUS(status); } @@ -170,7 +171,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) * * RETURN: Status * - * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, + * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, * increments the thread count, and waits at the method semaphore * for clearance to execute. * @@ -378,7 +379,8 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } info->parameters = &this_walk_state->operands[0]; @@ -444,7 +446,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, * RETURN: Status * * DESCRIPTION: Restart a method that was preempted by another (nested) method - * invocation. Handle the return value (if any) from the callee. + * invocation. Handle the return value (if any) from the callee. * ******************************************************************************/ @@ -530,7 +532,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, * * RETURN: None * - * DESCRIPTION: Terminate a control method. Delete everything that the method + * DESCRIPTION: Terminate a control method. Delete everything that the method * created, delete all locals and arguments, and delete the parse * tree if requested. * diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 8d55cebaa656..3da80460ce38 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,7 +76,7 @@ acpi_ds_method_data_get_type(u16 opcode, * RETURN: Status * * DESCRIPTION: Initialize the data structures that hold the method's arguments - * and locals. The data struct is an array of namespace nodes for + * and locals. The data struct is an array of namespace nodes for * each - this allows ref_of and de_ref_of to work properly for these * special data types. * @@ -129,7 +129,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) * * RETURN: None * - * DESCRIPTION: Delete method locals and arguments. Arguments are only + * DESCRIPTION: Delete method locals and arguments. Arguments are only * deleted if this method was called from another method. * ******************************************************************************/ @@ -183,7 +183,7 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) * * RETURN: Status * - * DESCRIPTION: Initialize arguments for a method. The parameter list is a list + * DESCRIPTION: Initialize arguments for a method. The parameter list is a list * of ACPI operand objects, either null terminated or whose length * is defined by max_param_count. * @@ -401,7 +401,7 @@ acpi_ds_method_data_get_value(u8 type, * This means that either 1) The expected argument was * not passed to the method, or 2) A local variable * was referenced by the method (via the ASL) - * before it was initialized. Either case is an error. + * before it was initialized. Either case is an error. */ /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ @@ -465,7 +465,7 @@ acpi_ds_method_data_get_value(u8 type, * * RETURN: None * - * DESCRIPTION: Delete the entry at Opcode:Index. Inserts + * DESCRIPTION: Delete the entry at Opcode:Index. Inserts * a null into the stack slot after the object is deleted. * ******************************************************************************/ @@ -523,7 +523,7 @@ acpi_ds_method_data_delete_value(u8 type, * * RETURN: Status * - * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed + * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed * as the new value for the Arg or Local and the reference count * for obj_desc is incremented. * @@ -566,7 +566,7 @@ acpi_ds_store_object_to_local(u8 type, /* * If the reference count on the object is more than one, we must - * take a copy of the object before we store. A reference count + * take a copy of the object before we store. A reference count * of exactly 1 means that the object was just created during the * evaluation of an expression, and we can safely use it since it * is not used anywhere else. diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 68592dd34960..e20e9f84eee8 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -293,7 +293,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, /* * Second arg is the buffer data (optional) byte_list can be either - * individual bytes or a string initializer. In either case, a + * individual bytes or a string initializer. In either case, a * byte_list appears in the AML. */ arg = op->common.value.arg; /* skip first arg */ @@ -388,7 +388,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, union acpi_parse_object *parent; union acpi_operand_object *obj_desc = NULL; acpi_status status = AE_OK; - unsigned i; + u32 i; u16 index; u16 reference_count; @@ -525,7 +525,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, } ACPI_INFO((AE_INFO, - "Actual Package length (%u) is larger than NumElements field (%u), truncated\n", + "Actual Package length (%u) is larger than NumElements field (%u), truncated", i, element_count)); } else if (i < element_count) { /* @@ -568,7 +568,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, /* * Because of the execution pass through the non-control-method - * parts of the table, we can arrive here twice. Only init + * parts of the table, we can arrive here twice. Only init * the named object node the first time through */ if (acpi_ns_get_attached_object(node)) { @@ -618,7 +618,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, * RETURN: Status * * DESCRIPTION: Initialize a namespace object from a parser Op and its - * associated arguments. The namespace object is a more compact + * associated arguments. The namespace object is a more compact * representation of the Op and its arguments. * ******************************************************************************/ @@ -703,7 +703,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Truncate value if we are executing from a 32-bit ACPI table */ #ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); + (void)acpi_ex_truncate_for32bit_table(obj_desc); #endif break; @@ -725,8 +725,18 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, case AML_TYPE_LITERAL: obj_desc->integer.value = op->common.value.integer; + #ifndef ACPI_NO_METHOD_EXECUTION - acpi_ex_truncate_for32bit_table(obj_desc); + if (acpi_ex_truncate_for32bit_table(obj_desc)) { + + /* Warn if we found a 64-bit constant in a 32-bit table */ + + ACPI_WARNING((AE_INFO, + "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X", + ACPI_FORMAT_UINT64(op->common. + value.integer), + (u32)obj_desc->integer.value)); + } #endif break; diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index aa34d8984d34..ee6367b8eaf7 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: dsopcode - Dispatcher suport for regions and fields + * Module Name: dsopcode - Dispatcher support for regions and fields * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -486,18 +486,18 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); /* - * This is where we evaluate the signature_string and oem_iDString - * and oem_table_iDString of the data_table_region declaration + * This is where we evaluate the Signature string, oem_id string, + * and oem_table_id string of the Data Table Region declaration */ node = op->common.node; - /* next_op points to signature_string op */ + /* next_op points to Signature string op */ next_op = op->common.value.arg; /* - * Evaluate/create the signature_string and oem_iDString - * and oem_table_iDString operands + * Evaluate/create the Signature string, oem_id string, + * and oem_table_id string operands */ status = acpi_ds_create_operands(walk_state, next_op); if (ACPI_FAILURE(status)) { @@ -505,8 +505,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, } /* - * Resolve the signature_string and oem_iDString - * and oem_table_iDString operands + * Resolve the Signature string, oem_id string, + * and oem_table_id string operands */ status = acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); @@ -649,7 +649,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) - && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { + && (op->common.parent->common.aml_opcode != + AML_NAME_OP))) { walk_state->result_obj = obj_desc; } } diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 73a5447475f5..4d8c992a51d8 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,7 @@ ACPI_MODULE_NAME("dsutils") * * RETURN: None. * - * DESCRIPTION: Clear and remove a reference on an implicit return value. Used + * DESCRIPTION: Clear and remove a reference on an implicit return value. Used * to delete "stale" return values (if enabled, the return value * from every operator is saved at least momentarily, in case the * parent method exits.) @@ -107,7 +107,7 @@ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) * * DESCRIPTION: Implements the optional "implicit return". We save the result * of every ASL operator and control method invocation in case the - * parent method exit. Before storing a new return value, we + * parent method exit. Before storing a new return value, we * delete the previous return value. * ******************************************************************************/ @@ -178,7 +178,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, if (!op) { ACPI_ERROR((AE_INFO, "Null Op")); - return_UINT8(TRUE); + return_VALUE(TRUE); } /* @@ -198,7 +198,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, * * If there is no parent, or the parent is a scope_op, we are executing * at the method level. An executing method typically has no parent, - * since each method is parsed separately. A method invoked externally + * since each method is parsed separately. A method invoked externally * via execute_control_method has a scope_op as the parent. */ if ((!op->common.parent) || @@ -210,7 +210,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, "At Method level, result of [%s] not used\n", acpi_ps_get_opcode_name(op->common. aml_opcode))); - return_UINT8(FALSE); + return_VALUE(FALSE); } /* Get info on the parent. The root_op is AML_SCOPE */ @@ -219,11 +219,11 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode); if (parent_info->class == AML_CLASS_UNKNOWN) { ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op)); - return_UINT8(FALSE); + return_VALUE(FALSE); } /* - * Decide what to do with the result based on the parent. If + * Decide what to do with the result based on the parent. If * the parent opcode will not use the result, delete the object. * Otherwise leave it as is, it will be deleted when it is used * as an operand later. @@ -266,7 +266,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, /* * These opcodes allow term_arg(s) as operands and therefore - * the operands can be method calls. The result is used. + * the operands can be method calls. The result is used. */ goto result_used; @@ -284,7 +284,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, AML_BANK_FIELD_OP)) { /* * These opcodes allow term_arg(s) as operands and therefore - * the operands can be method calls. The result is used. + * the operands can be method calls. The result is used. */ goto result_used; } @@ -307,7 +307,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_name(op->common.parent->common. aml_opcode), op)); - return_UINT8(TRUE); + return_VALUE(TRUE); result_not_used: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, @@ -316,7 +316,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op, acpi_ps_get_opcode_name(op->common.parent->common. aml_opcode), op)); - return_UINT8(FALSE); + return_VALUE(FALSE); } /******************************************************************************* @@ -329,9 +329,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, * * RETURN: Status * - * DESCRIPTION: Used after interpretation of an opcode. If there is an internal + * DESCRIPTION: Used after interpretation of an opcode. If there is an internal * result descriptor, check if the parent opcode will actually use - * this result. If not, delete the result now so that it will + * this result. If not, delete the result now so that it will * not become orphaned. * ******************************************************************************/ @@ -376,7 +376,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, * * RETURN: Status * - * DESCRIPTION: Resolve all operands to their values. Used to prepare + * DESCRIPTION: Resolve all operands to their values. Used to prepare * arguments to a control method invocation (a call from one * method to another.) * @@ -391,7 +391,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state) /* * Attempt to resolve each of the valid operands - * Method arguments are passed by reference, not by value. This means + * Method arguments are passed by reference, not by value. This means * that the actual objects are passed, not copies of the objects. */ for (i = 0; i < walk_state->num_operands; i++) { @@ -451,7 +451,7 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state) * RETURN: Status * * DESCRIPTION: Translate a parse tree object that is an argument to an AML - * opcode to the equivalent interpreter object. This may include + * opcode to the equivalent interpreter object. This may include * looking up a name or entering a new name into the internal * namespace. * @@ -496,9 +496,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* * Special handling for buffer_field declarations. This is a deferred * opcode that unfortunately defines the field name as the last - * parameter instead of the first. We get here when we are performing + * parameter instead of the first. We get here when we are performing * the deferred execution, so the actual name of the field is already - * in the namespace. We don't want to attempt to look it up again + * in the namespace. We don't want to attempt to look it up again * because we may be executing in a different scope than where the * actual opcode exists. */ @@ -560,7 +560,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * indicate this to the interpreter, set the * object to the root */ - obj_desc = ACPI_CAST_PTR(union + obj_desc = + ACPI_CAST_PTR(union acpi_operand_object, acpi_gbl_root_node); status = AE_OK; @@ -604,8 +605,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* * If the name is null, this means that this is an * optional result parameter that was not specified - * in the original ASL. Create a Zero Constant for a - * placeholder. (Store to a constant is a Noop.) + * in the original ASL. Create a Zero Constant for a + * placeholder. (Store to a constant is a Noop.) */ opcode = AML_ZERO_OP; /* Has no arguments! */ diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 642f3c053e87..44f8325c2bae 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,7 +57,7 @@ ACPI_MODULE_NAME("dswexec") /* * Dispatch table for opcode classes */ -static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = { +static acpi_execute_op acpi_gbl_op_type_dispatch[] = { acpi_ex_opcode_0A_0T_1R, acpi_ex_opcode_1A_0T_0R, acpi_ex_opcode_1A_0T_1R, @@ -149,7 +149,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, /* Truncate the predicate to 32-bits if necessary */ - acpi_ex_truncate_for32bit_table(local_obj_desc); + (void)acpi_ex_truncate_for32bit_table(local_obj_desc); /* * Save the result of the predicate evaluation on @@ -204,7 +204,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, * RETURN: Status * * DESCRIPTION: Descending callback used during the execution of control - * methods. This is where most operators and operands are + * methods. This is where most operators and operands are * dispatched to the interpreter. * ****************************************************************************/ @@ -297,7 +297,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, if (walk_state->walk_type & ACPI_WALK_METHOD) { /* * Found a named object declaration during method execution; - * we must enter this object into the namespace. The created + * we must enter this object into the namespace. The created * object is temporary and will be deleted upon completion of * the execution of this method. * @@ -348,7 +348,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, * RETURN: Status * * DESCRIPTION: Ascending callback used during the execution of control - * methods. The only thing we really need to do here is to + * methods. The only thing we really need to do here is to * notice the beginning of IF, ELSE, and WHILE blocks. * ****************************************************************************/ @@ -432,7 +432,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) if (ACPI_SUCCESS(status)) { /* * Dispatch the request to the appropriate interpreter handler - * routine. There is one routine per opcode "type" based upon the + * routine. There is one routine per opcode "type" based upon the * number of opcode arguments and return type. */ status = @@ -706,7 +706,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) * ACPI 2.0 support for 64-bit integers: Truncate numeric * result value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table(walk_state->result_obj); + (void)acpi_ex_truncate_for32bit_table(walk_state->result_obj); /* * Check if we just completed the evaluation of a diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 557510084c7a..6e17c0e24e63 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,7 +50,7 @@ #include "acnamesp.h" #ifdef ACPI_ASL_COMPILER -#include <acpi/acdisasm.h> +#include "acdisasm.h" #endif #define _COMPONENT ACPI_DISPATCHER @@ -178,7 +178,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); + acpi_dm_add_to_external_list(op, path, ACPI_TYPE_DEVICE, + 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index 89c0114210c0..4407ff2377d5 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -222,7 +222,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, */ ACPI_WARNING((AE_INFO, "Type override - [%4.4s] had invalid type (%s) " - "for Scope operator, changed to type ANY\n", + "for Scope operator, changed to type ANY", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); @@ -254,7 +254,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, acpi_ut_get_type_name(node->type), acpi_ut_get_node_name(node))); - return (AE_AML_OPERAND_TYPE); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } break; @@ -602,7 +602,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) region_space, walk_state); if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } acpi_ex_exit_interpreter(); diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index f6c4295470ae..d67891de1b54 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index d0e6555061e4..ecb12e2137ff 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,8 +51,9 @@ ACPI_MODULE_NAME("dswstate") /* Local prototypes */ -static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); -static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); +static acpi_status +acpi_ds_result_stack_push(struct acpi_walk_state *walk_state); +static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state); /******************************************************************************* * @@ -347,7 +348,7 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) * * RETURN: Status * - * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT * deleted by this routine. * ******************************************************************************/ @@ -491,7 +492,7 @@ acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, * RETURN: A walk_state object popped from the thread's stack * * DESCRIPTION: Remove and return the walkstate object that is at the head of - * the walk stack for the given walk list. NULL indicates that + * the walk stack for the given walk list. NULL indicates that * the list is empty. * ******************************************************************************/ @@ -531,14 +532,17 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) * * RETURN: Pointer to the new walk state. * - * DESCRIPTION: Allocate and initialize a new walk state. The current walk + * DESCRIPTION: Allocate and initialize a new walk state. The current walk * state is set to this new state. * ******************************************************************************/ -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *method_desc, struct acpi_thread_state +struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, + union acpi_parse_object + *origin, + union acpi_operand_object + *method_desc, + struct acpi_thread_state *thread) { struct acpi_walk_state *walk_state; @@ -653,7 +657,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, /* * Setup the current scope. * Find a Named Op that has a namespace node associated with it. - * search upwards from this Op. Current scope is the first + * search upwards from this Op. Current scope is the first * Op with a namespace node. */ extra_op = parser_state->start_op; @@ -704,13 +708,13 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); if (!walk_state) { - return; + return_VOID; } if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { ACPI_ERROR((AE_INFO, "%p is not a valid walk state", walk_state)); - return; + return_VOID; } /* There should not be any open scopes */ diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index d4acfbbe5b29..b8ea0b26cde3 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index af14a7137632..a621481c6cf2 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index ef0193d74b5d..b9adb9a7ed85 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,7 +89,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) /* Set the mask bit only if there are references to this GPE */ if (gpe_event_info->runtime_count) { - ACPI_SET_BIT(gpe_register_info->enable_for_run, (u8)register_bit); + ACPI_SET_BIT(gpe_register_info->enable_for_run, + (u8)register_bit); } return_ACPI_STATUS(AE_OK); @@ -106,8 +107,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) * DESCRIPTION: Clear a GPE of stale events and enable it. * ******************************************************************************/ -acpi_status -acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) +acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status; @@ -131,8 +131,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) } /* Enable the requested GPE */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); return_ACPI_STATUS(status); } @@ -150,7 +150,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) * ******************************************************************************/ -acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) +acpi_status +acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status = AE_OK; @@ -191,7 +192,8 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info * ******************************************************************************/ -acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) +acpi_status +acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) { acpi_status status = AE_OK; @@ -208,7 +210,8 @@ acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_i status = acpi_ev_update_gpe_enable_mask(gpe_event_info); if (ACPI_SUCCESS(status)) { - status = acpi_hw_low_set_gpe(gpe_event_info, + status = + acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); } @@ -306,7 +309,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, /* A Non-NULL gpe_device means this is a GPE Block Device */ - obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) + obj_desc = + acpi_ns_get_attached_object((struct acpi_namespace_node *) gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); @@ -557,8 +561,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) status = AE_NO_MEMORY; } else { /* - * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx - * control method that corresponds to this GPE + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the + * _Lxx/_Exx control method that corresponds to this GPE */ info->prefix_node = local_gpe_event_info->dispatch.method_node; @@ -703,7 +707,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to clear GPE%02X", gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); } } @@ -720,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to disable GPE%02X", gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + return_VALUE(ACPI_INTERRUPT_NOT_HANDLED); } /* @@ -761,7 +765,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Unable to queue handler for GPE%2X - event disabled", + "Unable to queue handler for GPE%02X - event disabled", gpe_number)); } break; @@ -780,7 +784,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, break; } - return_UINT32(ACPI_INTERRUPT_HANDLED); + return_VALUE(ACPI_INTERRUPT_HANDLED); } #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 8cf4c104c7b7..a2d688bbac02 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -405,13 +405,13 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, (*return_gpe_block) = gpe_block; } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", - (u32) gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - (gpe_block->gpe_count - 1)), - gpe_device->name.ascii, gpe_block->register_count, - interrupt_number)); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X\n", + (u32)gpe_block->block_base_number, + (u32)(gpe_block->block_base_number + + (gpe_block->gpe_count - 1)), + gpe_device->name.ascii, gpe_block->register_count, + interrupt_number)); /* Update global count of currently available GPEs */ @@ -486,7 +486,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not enable GPE 0x%02X", - gpe_index + gpe_block->block_base_number)); + gpe_index + + gpe_block->block_base_number)); continue; } @@ -495,9 +496,11 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, } if (gpe_enabled_count) { - ACPI_DEBUG_PRINT((ACPI_DB_INIT, - "Enabled %u GPEs in this block\n", - gpe_enabled_count)); + ACPI_INFO((AE_INFO, + "Enabled %u GPEs in block %02X to %02X", + gpe_enabled_count, (u32)gpe_block->block_base_number, + (u32)(gpe_block->block_base_number + + (gpe_block->gpe_count - 1)))); } gpe_block->initialized = TRUE; diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index da0add858f81..72b8f6b3f4ca 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,6 +86,9 @@ acpi_status acpi_ev_gpe_initialize(void) ACPI_FUNCTION_TRACE(ev_gpe_initialize); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "Initializing General Purpose Events (GPEs):\n")); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index cb50dd91bc18..b24dbb80fab8 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -374,7 +374,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, gpe_event_info->dispatch.handler = NULL; gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; - } else if ((gpe_event_info-> + } else + if ((gpe_event_info-> flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_NOTIFY) { diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c new file mode 100644 index 000000000000..d4f83112c2e2 --- /dev/null +++ b/drivers/acpi/acpica/evhandler.c @@ -0,0 +1,529 @@ +/****************************************************************************** + * + * Module Name: evhandler - Support for Address Space handlers + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS +ACPI_MODULE_NAME("evhandler") + +/* Local prototypes */ +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value); + +/* These are the address spaces that will get default handlers */ + +u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE +}; + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_region_handlers + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem default address space handlers. + * + ******************************************************************************/ + +acpi_status acpi_ev_install_region_handlers(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ev_install_region_handlers); + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * All address spaces (PCI Config, EC, SMBus) are scope dependent and + * registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is + * currently no device associated with the address space. For these we + * use the root. + * + * We install the default PCI config space handler at the root so that + * this space is immediately available even though the we have not + * enumerated all the PCI Root Buses yet. This is to conform to the ACPI + * specification which states that the PCI config space must be always + * available -- even though we are nowhere near ready to find the PCI root + * buses at this point. + * + * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. + */ + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_ev_install_space_handler(acpi_gbl_root_node, + acpi_gbl_default_address_spaces + [i], + ACPI_DEFAULT_HANDLER, + NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + status = AE_OK; + break; + + default: + + goto unlock_and_exit; + } + } + + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_has_default_handler + * + * PARAMETERS: node - Namespace node for the device + * space_id - The address space ID + * + * RETURN: TRUE if default handler is installed, FALSE otherwise + * + * DESCRIPTION: Check if the default handler is installed for the requested + * space ID. + * + ******************************************************************************/ + +u8 +acpi_ev_has_default_handler(struct acpi_namespace_node *node, + acpi_adr_space_type space_id) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + + /* Must have an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + handler_obj = obj_desc->device.handler; + + /* Walk the linked list of handlers for this object */ + + while (handler_obj) { + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { + return (TRUE); + } + } + + handler_obj = handler_obj->address_space.next; + } + } + + return (FALSE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_handler + * + * PARAMETERS: walk_namespace callback + * + * DESCRIPTION: This routine installs an address handler into objects that are + * of type Region or Device. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ******************************************************************************/ + +static acpi_status +acpi_ev_install_handler(acpi_handle obj_handle, + u32 level, void *context, void **return_value) +{ + union acpi_operand_object *handler_obj; + union acpi_operand_object *next_handler_obj; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + acpi_status status; + + ACPI_FUNCTION_NAME(ev_install_handler); + + handler_obj = (union acpi_operand_object *)context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_validate_handle(obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions and objects that are allowed to have + * address space handlers + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + + /* No object, just exit */ + + return (AE_OK); + } + + /* Devices are handled different than regions */ + + if (obj_desc->common.type == ACPI_TYPE_DEVICE) { + + /* Check if this Device already has a handler for this address space */ + + next_handler_obj = obj_desc->device.handler; + while (next_handler_obj) { + + /* Found a handler, is it for the same address space? */ + + if (next_handler_obj->address_space.space_id == + handler_obj->address_space.space_id) { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Found handler for region [%s] in device %p(%p) " + "handler %p\n", + acpi_ut_get_region_name + (handler_obj->address_space. + space_id), obj_desc, + next_handler_obj, + handler_obj)); + + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* Walk the linked list of handlers attached to this device */ + + next_handler_obj = next_handler_obj->address_space.next; + } + + /* + * As long as the device didn't have a handler for this space we + * don't care about it. We just ignore it and proceed. + */ + return (AE_OK); + } + + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { + + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address space type. + * + * First disconnect region for any previous handler (if any) + */ + acpi_ev_detach_region(obj_desc, FALSE); + + /* Connect the region to the new handler */ + + status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_install_space_handler + * + * PARAMETERS: node - Namespace node for the device + * space_id - The address space ID + * handler - Address of the handler + * setup - Address of the setup function + * context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all op_regions of a given space_id. + * Assumes namespace is locked + * + ******************************************************************************/ + +acpi_status +acpi_ev_install_space_handler(struct acpi_namespace_node * node, + acpi_adr_space_type space_id, + acpi_adr_space_handler handler, + acpi_adr_space_setup setup, void *context) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + acpi_status status; + acpi_object_type type; + u8 flags = 0; + + ACPI_FUNCTION_TRACE(ev_install_space_handler); + + /* + * This registration is valid for only the types below and the root. This + * is where the default handlers get placed. + */ + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + handler = acpi_ex_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: + handler = acpi_ex_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_CONFIG: + handler = acpi_ex_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + case ACPI_ADR_SPACE_CMOS: + handler = acpi_ex_cmos_space_handler; + setup = acpi_ev_cmos_region_setup; + break; + + case ACPI_ADR_SPACE_PCI_BAR_TARGET: + handler = acpi_ex_pci_bar_space_handler; + setup = acpi_ev_pci_bar_region_setup; + break; + + case ACPI_ADR_SPACE_DATA_TABLE: + handler = acpi_ex_data_table_space_handler; + setup = NULL; + break; + + default: + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* If the caller hasn't specified a setup routine, use the default */ + + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + /* + * The attached device object already exists. Make sure the handler + * is not already installed. + */ + handler_obj = obj_desc->device.handler; + + /* Walk the handler list for this device */ + + while (handler_obj) { + + /* Same space_id indicates a handler already installed */ + + if (handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == + handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with the + * PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } + goto unlock_and_exit; + } + + /* Walk the linked list of handlers */ + + handler_obj = handler_obj->address_space.next; + } + } else { + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Creating object on Device %p while installing handler\n", + node)); + + /* obj_desc does not exist, create one */ + + if (node->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } else { + type = node->type; + } + + obj_desc = acpi_ut_create_internal_object(type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8)type; + + /* Attach the new object to the Node */ + + status = acpi_ns_attach_object(node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference(obj_desc); + + if (ACPI_FAILURE(status)) { + goto unlock_and_exit; + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", + acpi_ut_get_region_name(space_id), space_id, + acpi_ut_get_node_name(node), node, obj_desc)); + + /* + * Install the handler + * + * At this point there is no existing handler. Just allocate the object + * for the handler and link it into the list. + */ + handler_obj = + acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8)space_id; + handler_obj->address_space.handler_flags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.handler; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.handler = handler_obj; + + /* + * Walk the namespace finding all of the regions this + * handler will manage. + * + * Start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case, back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, + acpi_ev_install_handler, NULL, + handler_obj, NULL); + + unlock_and_exit: + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 51f537937c1f..c986b2336b81 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 0cc6a16fedc7..6555e350fc1f 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -1,11 +1,11 @@ /****************************************************************************** * - * Module Name: evregion - ACPI address_space (op_region) handler dispatch + * Module Name: evregion - Operation Region support * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,10 +50,9 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evregion") +extern u8 acpi_gbl_default_address_spaces[]; + /* Local prototypes */ -static u8 -acpi_ev_has_default_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id); static void acpi_ev_orphan_ec_reg_method(void); @@ -61,135 +60,6 @@ static acpi_status acpi_ev_reg_run(acpi_handle obj_handle, u32 level, void *context, void **return_value); -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value); - -/* These are the address spaces that will get default handlers */ - -#define ACPI_NUM_DEFAULT_SPACES 4 - -static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_ADR_SPACE_DATA_TABLE -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_region_handlers - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Installs the core subsystem default address space handlers. - * - ******************************************************************************/ - -acpi_status acpi_ev_install_region_handlers(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ev_install_region_handlers); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * All address spaces (PCI Config, EC, SMBus) are scope dependent and - * registration must occur for a specific device. - * - * In the case of the system memory and IO address spaces there is - * currently no device associated with the address space. For these we - * use the root. - * - * We install the default PCI config space handler at the root so that - * this space is immediately available even though the we have not - * enumerated all the PCI Root Buses yet. This is to conform to the ACPI - * specification which states that the PCI config space must be always - * available -- even though we are nowhere near ready to find the PCI root - * buses at this point. - * - * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler). - * Similar for AE_SAME_HANDLER. - */ - for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { - status = acpi_ev_install_space_handler(acpi_gbl_root_node, - acpi_gbl_default_address_spaces - [i], - ACPI_DEFAULT_HANDLER, - NULL, NULL); - switch (status) { - case AE_OK: - case AE_SAME_HANDLER: - case AE_ALREADY_EXISTS: - - /* These exceptions are all OK */ - - status = AE_OK; - break; - - default: - - goto unlock_and_exit; - } - } - - unlock_and_exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_has_default_handler - * - * PARAMETERS: node - Namespace node for the device - * space_id - The address space ID - * - * RETURN: TRUE if default handler is installed, FALSE otherwise - * - * DESCRIPTION: Check if the default handler is installed for the requested - * space ID. - * - ******************************************************************************/ - -static u8 -acpi_ev_has_default_handler(struct acpi_namespace_node *node, - acpi_adr_space_type space_id) -{ - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; - - /* Must have an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - handler_obj = obj_desc->device.handler; - - /* Walk the linked list of handlers for this object */ - - while (handler_obj) { - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { - return (TRUE); - } - } - - handler_obj = handler_obj->address_space.next; - } - } - - return (FALSE); -} - /******************************************************************************* * * FUNCTION: acpi_ev_initialize_op_regions @@ -241,91 +111,6 @@ acpi_status acpi_ev_initialize_op_regions(void) /******************************************************************************* * - * FUNCTION: acpi_ev_execute_reg_method - * - * PARAMETERS: region_obj - Region object - * function - Passed to _REG: On (1) or Off (0) - * - * RETURN: Status - * - * DESCRIPTION: Execute _REG method for a region - * - ******************************************************************************/ - -acpi_status -acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) -{ - struct acpi_evaluate_info *info; - union acpi_operand_object *args[3]; - union acpi_operand_object *region_obj2; - acpi_status status; - - ACPI_FUNCTION_TRACE(ev_execute_reg_method); - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - if (region_obj2->extra.method_REG == NULL) { - return_ACPI_STATUS(AE_OK); - } - - /* Allocate and initialize the evaluation information block */ - - info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - info->prefix_node = region_obj2->extra.method_REG; - info->pathname = NULL; - info->parameters = args; - info->flags = ACPI_IGNORE_RETURN_VALUE; - - /* - * The _REG method has two arguments: - * - * arg0 - Integer: - * Operation region space ID Same value as region_obj->Region.space_id - * - * arg1 - Integer: - * connection status 1 for connecting the handler, 0 for disconnecting - * the handler (Passed as a parameter) - */ - args[0] = - acpi_ut_create_integer_object((u64) region_obj->region.space_id); - if (!args[0]) { - status = AE_NO_MEMORY; - goto cleanup1; - } - - args[1] = acpi_ut_create_integer_object((u64) function); - if (!args[1]) { - status = AE_NO_MEMORY; - goto cleanup2; - } - - args[2] = NULL; /* Terminate list */ - - /* Execute the method, no return value */ - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - - status = acpi_ns_evaluate(info); - acpi_ut_remove_reference(args[1]); - - cleanup2: - acpi_ut_remove_reference(args[0]); - - cleanup1: - ACPI_FREE(info); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ev_address_space_dispatch * * PARAMETERS: region_obj - Internal region object @@ -709,351 +494,86 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, /******************************************************************************* * - * FUNCTION: acpi_ev_install_handler - * - * PARAMETERS: walk_namespace callback - * - * DESCRIPTION: This routine installs an address handler into objects that are - * of type Region or Device. - * - * If the Object is a Device, and the device has a handler of - * the same type then the search is terminated in that branch. - * - * This is because the existing handler is closer in proximity - * to any more regions than the one we are trying to install. - * - ******************************************************************************/ - -static acpi_status -acpi_ev_install_handler(acpi_handle obj_handle, - u32 level, void *context, void **return_value) -{ - union acpi_operand_object *handler_obj; - union acpi_operand_object *next_handler_obj; - union acpi_operand_object *obj_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_NAME(ev_install_handler); - - handler_obj = (union acpi_operand_object *)context; - - /* Parameter validation */ - - if (!handler_obj) { - return (AE_OK); - } - - /* Convert and validate the device handle */ - - node = acpi_ns_validate_handle(obj_handle); - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* - * We only care about regions and objects that are allowed to have - * address space handlers - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { - return (AE_OK); - } - - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - - /* No object, just exit */ - - return (AE_OK); - } - - /* Devices are handled different than regions */ - - if (obj_desc->common.type == ACPI_TYPE_DEVICE) { - - /* Check if this Device already has a handler for this address space */ - - next_handler_obj = obj_desc->device.handler; - while (next_handler_obj) { - - /* Found a handler, is it for the same address space? */ - - if (next_handler_obj->address_space.space_id == - handler_obj->address_space.space_id) { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler for region [%s] in device %p(%p) " - "handler %p\n", - acpi_ut_get_region_name - (handler_obj->address_space. - space_id), obj_desc, - next_handler_obj, - handler_obj)); - - /* - * Since the object we found it on was a device, then it - * means that someone has already installed a handler for - * the branch of the namespace from this device on. Just - * bail out telling the walk routine to not traverse this - * branch. This preserves the scoping rule for handlers. - */ - return (AE_CTRL_DEPTH); - } - - /* Walk the linked list of handlers attached to this device */ - - next_handler_obj = next_handler_obj->address_space.next; - } - - /* - * As long as the device didn't have a handler for this space we - * don't care about it. We just ignore it and proceed. - */ - return (AE_OK); - } - - /* Object is a Region */ - - if (obj_desc->region.space_id != handler_obj->address_space.space_id) { - - /* This region is for a different address space, just ignore it */ - - return (AE_OK); - } - - /* - * Now we have a region and it is for the handler's address space type. - * - * First disconnect region for any previous handler (if any) - */ - acpi_ev_detach_region(obj_desc, FALSE); - - /* Connect the region to the new handler */ - - status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ev_install_space_handler + * FUNCTION: acpi_ev_execute_reg_method * - * PARAMETERS: node - Namespace node for the device - * space_id - The address space ID - * handler - Address of the handler - * setup - Address of the setup function - * context - Value passed to the handler on each access + * PARAMETERS: region_obj - Region object + * function - Passed to _REG: On (1) or Off (0) * * RETURN: Status * - * DESCRIPTION: Install a handler for all op_regions of a given space_id. - * Assumes namespace is locked + * DESCRIPTION: Execute _REG method for a region * ******************************************************************************/ acpi_status -acpi_ev_install_space_handler(struct acpi_namespace_node * node, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context) +acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) { - union acpi_operand_object *obj_desc; - union acpi_operand_object *handler_obj; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; + union acpi_operand_object *region_obj2; acpi_status status; - acpi_object_type type; - u8 flags = 0; - ACPI_FUNCTION_TRACE(ev_install_space_handler); - - /* - * This registration is valid for only the types below and the root. This - * is where the default handlers get placed. - */ - if ((node->type != ACPI_TYPE_DEVICE) && - (node->type != ACPI_TYPE_PROCESSOR) && - (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + ACPI_FUNCTION_TRACE(ev_execute_reg_method); - if (handler == ACPI_DEFAULT_HANDLER) { - flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; - - switch (space_id) { - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - handler = acpi_ex_system_memory_space_handler; - setup = acpi_ev_system_memory_region_setup; - break; - - case ACPI_ADR_SPACE_SYSTEM_IO: - handler = acpi_ex_system_io_space_handler; - setup = acpi_ev_io_space_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_CONFIG: - handler = acpi_ex_pci_config_space_handler; - setup = acpi_ev_pci_config_region_setup; - break; - - case ACPI_ADR_SPACE_CMOS: - handler = acpi_ex_cmos_space_handler; - setup = acpi_ev_cmos_region_setup; - break; - - case ACPI_ADR_SPACE_PCI_BAR_TARGET: - handler = acpi_ex_pci_bar_space_handler; - setup = acpi_ev_pci_bar_region_setup; - break; - - case ACPI_ADR_SPACE_DATA_TABLE: - handler = acpi_ex_data_table_space_handler; - setup = NULL; - break; - - default: - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } + region_obj2 = acpi_ns_get_secondary_object(region_obj); + if (!region_obj2) { + return_ACPI_STATUS(AE_NOT_EXIST); } - /* If the caller hasn't specified a setup routine, use the default */ - - if (!setup) { - setup = acpi_ev_default_region_setup; + if (region_obj2->extra.method_REG == NULL) { + return_ACPI_STATUS(AE_OK); } - /* Check for an existing internal object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (obj_desc) { - /* - * The attached device object already exists. Make sure the handler - * is not already installed. - */ - handler_obj = obj_desc->device.handler; - - /* Walk the handler list for this device */ - - while (handler_obj) { - - /* Same space_id indicates a handler already installed */ - - if (handler_obj->address_space.space_id == space_id) { - if (handler_obj->address_space.handler == - handler) { - /* - * It is (relatively) OK to attempt to install the SAME - * handler twice. This can easily happen with the - * PCI_Config space. - */ - status = AE_SAME_HANDLER; - goto unlock_and_exit; - } else { - /* A handler is already installed */ - - status = AE_ALREADY_EXISTS; - } - goto unlock_and_exit; - } - - /* Walk the linked list of handlers */ - - handler_obj = handler_obj->address_space.next; - } - } else { - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Creating object on Device %p while installing handler\n", - node)); - - /* obj_desc does not exist, create one */ - - if (node->type == ACPI_TYPE_ANY) { - type = ACPI_TYPE_DEVICE; - } else { - type = node->type; - } - - obj_desc = acpi_ut_create_internal_object(type); - if (!obj_desc) { - status = AE_NO_MEMORY; - goto unlock_and_exit; - } - - /* Init new descriptor */ - - obj_desc->common.type = (u8) type; - - /* Attach the new object to the Node */ - - status = acpi_ns_attach_object(node, obj_desc, type); - - /* Remove local reference to the object */ - - acpi_ut_remove_reference(obj_desc); + /* Allocate and initialize the evaluation information block */ - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", - acpi_ut_get_region_name(space_id), space_id, - acpi_ut_get_node_name(node), node, obj_desc)); + info->prefix_node = region_obj2->extra.method_REG; + info->pathname = NULL; + info->parameters = args; + info->flags = ACPI_IGNORE_RETURN_VALUE; /* - * Install the handler + * The _REG method has two arguments: + * + * arg0 - Integer: + * Operation region space ID Same value as region_obj->Region.space_id * - * At this point there is no existing handler. Just allocate the object - * for the handler and link it into the list. + * arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) */ - handler_obj = - acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER); - if (!handler_obj) { + args[0] = + acpi_ut_create_integer_object((u64)region_obj->region.space_id); + if (!args[0]) { status = AE_NO_MEMORY; - goto unlock_and_exit; + goto cleanup1; } - /* Init handler obj */ + args[1] = acpi_ut_create_integer_object((u64)function); + if (!args[1]) { + status = AE_NO_MEMORY; + goto cleanup2; + } - handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.handler_flags = flags; - handler_obj->address_space.region_list = NULL; - handler_obj->address_space.node = node; - handler_obj->address_space.handler = handler; - handler_obj->address_space.context = context; - handler_obj->address_space.setup = setup; + args[2] = NULL; /* Terminate list */ - /* Install at head of Device.address_space list */ + /* Execute the method, no return value */ - handler_obj->address_space.next = obj_desc->device.handler; + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - /* - * The Device object is the first reference on the handler_obj. - * Each region that uses the handler adds a reference. - */ - obj_desc->device.handler = handler_obj; + status = acpi_ns_evaluate(info); + acpi_ut_remove_reference(args[1]); - /* - * Walk the namespace finding all of the regions this - * handler will manage. - * - * Start at the device and search the branch toward - * the leaf nodes until either the leaf is encountered or - * a device is detected that has an address handler of the - * same type. - * - * In either case, back up and search down the remainder - * of the branch - */ - status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, - acpi_ev_install_handler, NULL, - handler_obj, NULL); + cleanup2: + acpi_ut_remove_reference(args[0]); - unlock_and_exit: + cleanup1: + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 4c1c8261166f..3bb616794b3b 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -227,8 +227,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* Install a handler for this PCI root bridge */ - status = - acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE(status)) { if (status == AE_SAME_HANDLER) { /* @@ -350,8 +349,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) { acpi_status status; - struct acpica_device_id *hid; - struct acpica_device_id_list *cid; + struct acpi_pnp_device_id *hid; + struct acpi_pnp_device_id_list *cid; u32 i; u8 match; diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index f9661e2b46a9..f4b43bede015 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,7 +89,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) */ interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); + return_VALUE(interrupt_handled); } /******************************************************************************* @@ -120,7 +120,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); - return_UINT32(interrupt_handled); + return_VALUE(interrupt_handled); } /****************************************************************************** diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 7587eb6c9584..ddffd6847914 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,13 +56,13 @@ ACPI_MODULE_NAME("evxface") * * FUNCTION: acpi_install_notify_handler * - * PARAMETERS: Device - The device for which notifies will be handled + * PARAMETERS: device - The device for which notifies will be handled * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) * ACPI_ALL_NOTIFY: Both System and Device - * Handler - Address of the handler - * Context - Value passed to the handler on each GPE + * handler - Address of the handler + * context - Value passed to the handler on each GPE * * RETURN: Status * @@ -217,12 +217,12 @@ ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) * * FUNCTION: acpi_remove_notify_handler * - * PARAMETERS: Device - The device for which the handler is installed + * PARAMETERS: device - The device for which the handler is installed * handler_type - The type of handler: * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) * ACPI_ALL_NOTIFY: Both System and Device - * Handler - Address of the handler + * handler - Address of the handler * * RETURN: Status * @@ -249,7 +249,8 @@ acpi_remove_notify_handler(acpi_handle device, (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Make sure all deferred tasks are completed */ + + /* Make sure all deferred notify tasks are completed */ acpi_os_wait_events_complete(); @@ -398,7 +399,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) * ******************************************************************************/ acpi_status -acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context) +acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) { acpi_status status; @@ -596,7 +597,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(status); } - /* Allocate memory for the handler object */ + /* Allocate and init handler object (before lock) */ handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info)); if (!handler) { @@ -622,16 +623,15 @@ acpi_install_gpe_handler(acpi_handle gpe_device, goto free_and_exit; } - /* Allocate and init handler object */ - handler->address = address; handler->context = context; handler->method_node = gpe_event_info->dispatch.method_node; - handler->original_flags = gpe_event_info->flags & - (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); + handler->original_flags = (u8)(gpe_event_info->flags & + (ACPI_GPE_XRUPT_TYPE_MASK | + ACPI_GPE_DISPATCH_MASK)); /* - * If the GPE is associated with a method, it might have been enabled + * If the GPE is associated with a method, it may have been enabled * automatically during initialization, in which case it has to be * disabled now to avoid spurious execution of the handler. */ @@ -646,7 +646,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device, gpe_event_info->dispatch.handler = handler; - /* Setup up dispatch flags to indicate handler (vs. method) */ + /* Setup up dispatch flags to indicate handler (vs. method/notify) */ gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); @@ -697,7 +697,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Make sure all deferred tasks are completed */ + /* Make sure all deferred GPE tasks are completed */ acpi_os_wait_events_complete(); @@ -747,10 +747,10 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, * enabled, it should be enabled at this point to restore the * post-initialization configuration. */ - - if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) - && handler->originally_enabled) + if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) && + handler->originally_enabled) { (void)acpi_ev_add_gpe_reference(gpe_event_info); + } /* Now we can free the handler object */ diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 35520c6eeefb..d6e4e42316db 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,6 @@ ACPI_MODULE_NAME("evxfevnt") * DESCRIPTION: Transfers the system into ACPI mode. * ******************************************************************************/ - acpi_status acpi_enable(void) { acpi_status status; @@ -210,8 +209,8 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) * * FUNCTION: acpi_disable_event * - * PARAMETERS: Event - The fixed eventto be enabled - * Flags - Reserved + * PARAMETERS: event - The fixed event to be disabled + * flags - Reserved * * RETURN: Status * diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 87c5f2332260..aff4cc261211 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evxfgpe") #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_update_all_gpes * @@ -172,6 +172,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } + ACPI_EXPORT_SYMBOL(acpi_disable_gpe) @@ -221,10 +222,11 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, if (wake_device == ACPI_ROOT_OBJECT) { device_node = acpi_gbl_root_node; } else { - device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); + device_node = + ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); } - /* Validate WakeDevice is of type Device */ + /* Validate wake_device is of type Device */ if (device_node->type != ACPI_TYPE_DEVICE) { return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -324,7 +326,8 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) * ******************************************************************************/ -acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) +acpi_status +acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; @@ -430,8 +433,8 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe) * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 * gpe_number - GPE level within the GPE block - * event_status - Where the current status of the event will - * be returned + * event_status - Where the current status of the event + * will be returned * * RETURN: Status * @@ -567,7 +570,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } node = acpi_ns_validate_handle(gpe_device); @@ -650,7 +653,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } node = acpi_ns_validate_handle(gpe_device); @@ -694,8 +697,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) * the FADT-defined gpe blocks. Otherwise, the GPE block device. * ******************************************************************************/ -acpi_status -acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) +acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device) { struct acpi_gpe_device_info info; acpi_status status; diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 96b412d03950..96c9e5f355ae 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 16219bde48da..d93b70be60ad 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,7 @@ #include "actables.h" #include "acdispat.h" #include "acevents.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exconfig") @@ -120,8 +121,11 @@ acpi_ex_add_table(u32 table_index, acpi_ns_exec_module_code_list(); acpi_ex_enter_interpreter(); - /* Update GPEs for any new _Lxx/_Exx methods. Ignore errors */ - + /* + * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is + * responsible for discovering any new wake GPEs by running _PRW methods + * that may have been loaded by this table. + */ status = acpi_tb_get_owner_id(table_index, &owner_id); if (ACPI_SUCCESS(status)) { acpi_ev_update_gpes(owner_id); @@ -158,12 +162,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); - /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ + /* Validate lengths for the Signature, oem_id, and oem_table_id strings */ if ((operand[0]->string.length > ACPI_NAME_SIZE) || (operand[1]->string.length > ACPI_OEM_ID_SIZE) || (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_AML_STRING_LIMIT); } /* Find the ACPI table in the RSDT/XSDT */ @@ -210,8 +214,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, /* parameter_path (optional parameter) */ if (operand[4]->string.length > 0) { - if ((operand[4]->string.pointer[0] != '\\') && - (operand[4]->string.pointer[0] != '^')) { + if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) && + (operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) { /* * Path is not absolute, so it will be relative to the node * referenced by the root_path_string (or the NS root if omitted) @@ -301,7 +305,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ, region_offset, 8, &value); if (ACPI_FAILURE(status)) { - return status; + return (status); } *buffer = (u8)value; @@ -309,7 +313,7 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) region_offset++; } - return AE_OK; + return (AE_OK); } /******************************************************************************* diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index bfb062e4c4b4..d2b9613bbf01 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,7 +176,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* Save the Result */ - acpi_ex_truncate_for32bit_table(return_desc); + (void)acpi_ex_truncate_for32bit_table(return_desc); *result_desc = return_desc; return_ACPI_STATUS(AE_OK); } @@ -516,8 +516,8 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, string_length--; } - return_desc = acpi_ut_create_string_object((acpi_size) - string_length); + return_desc = + acpi_ut_create_string_object((acpi_size) string_length); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 691d4763102c..26a13f67977e 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -78,7 +78,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { /* * Dereference an existing alias so that we don't create a chain - * of aliases. With this code, we guarantee that an alias is + * of aliases. With this code, we guarantee that an alias is * always exactly one level of indirection away from the * actual aliased name. */ @@ -90,7 +90,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) /* * For objects that can never change (i.e., the NS node will * permanently point to the same object), we can simply attach - * the object to the new NS node. For other objects (such as + * the object to the new NS node. For other objects (such as * Integers, buffers, etc.), we have to point the Alias node * to the original Node. */ @@ -139,7 +139,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) /* * The new alias assumes the type of the target, and it points - * to the same object. The reference count of the object has an + * to the same object. The reference count of the object has an * additional reference to prevent deletion out from under either the * target node or the alias Node */ @@ -243,8 +243,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) /* Init object and attach to NS node */ - obj_desc->mutex.sync_level = - (u8) walk_state->operands[1]->integer.value; + obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value; obj_desc->mutex.node = (struct acpi_namespace_node *)walk_state->operands[0]; diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index bc5b9a6a1316..7eb853cd279f 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -145,10 +145,10 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, case ACPI_TYPE_BUFFER: acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length); - acpi_ut_dump_buffer2(source_desc->buffer.pointer, - (source_desc->buffer.length < 256) ? - source_desc->buffer.length : 256, - DB_BYTE_DISPLAY); + acpi_ut_dump_buffer(source_desc->buffer.pointer, + (source_desc->buffer.length < 256) ? + source_desc->buffer.length : 256, + DB_BYTE_DISPLAY, 0); break; case ACPI_TYPE_STRING: @@ -190,7 +190,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, acpi_os_printf("Table Index 0x%X\n", source_desc->reference.value); - return; + return_VOID; default: break; diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 213c081776fc..e5a3c249f7fa 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -464,8 +464,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) ACPI_FUNCTION_NAME(ex_dump_operand) - if (!((ACPI_LV_EXEC & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + /* Check if debug output enabled */ + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_EXEC, _COMPONENT)) { return; } @@ -777,7 +777,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands, * PARAMETERS: title - Descriptive text * value - Value to be displayed * - * DESCRIPTION: Object dump output formatting functions. These functions + * DESCRIPTION: Object dump output formatting functions. These functions * reduce the number of format strings required and keeps them * all in one place for easy modification. * @@ -810,8 +810,10 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) ACPI_FUNCTION_ENTRY(); if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_OBJECTS, _COMPONENT)) { return; } } @@ -940,10 +942,11 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, acpi_os_printf("[Buffer] Length %.2X = ", obj_desc->buffer.length); if (obj_desc->buffer.length) { - acpi_ut_dump_buffer(ACPI_CAST_PTR - (u8, obj_desc->buffer.pointer), - obj_desc->buffer.length, - DB_DWORD_DISPLAY, _COMPONENT); + acpi_ut_debug_dump_buffer(ACPI_CAST_PTR + (u8, + obj_desc->buffer.pointer), + obj_desc->buffer.length, + DB_DWORD_DISPLAY, _COMPONENT); } else { acpi_os_printf("\n"); } @@ -996,8 +999,10 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) } if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_OBJECTS, _COMPONENT)) { return_VOID; } } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index dc092f5b35d6..7d4bae71e8c6 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,7 +59,7 @@ ACPI_MODULE_NAME("exfield") * * RETURN: Status * - * DESCRIPTION: Read from a named field. Returns either an Integer or a + * DESCRIPTION: Read from a named field. Returns either an Integer or a * Buffer, depending on the size of the field. * ******************************************************************************/ @@ -149,7 +149,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, * Allocate a buffer for the contents of the field. * * If the field is larger than the current integer width, create - * a BUFFER to hold it. Otherwise, use an INTEGER. This allows + * a BUFFER to hold it. Otherwise, use an INTEGER. This allows * the use of arithmetic operators on the returned value if the * field size is equal or smaller than an Integer. * diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index a7784152ed30..ec7f5690031b 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,8 +54,7 @@ ACPI_MODULE_NAME("exfldio") /* Local prototypes */ static acpi_status acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, - u32 field_datum_byte_offset, - u64 *value, u32 read_write); + u32 field_datum_byte_offset, u64 *value, u32 read_write); static u8 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value); @@ -155,7 +154,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, #endif /* - * Validate the request. The entire request from the byte offset for a + * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ @@ -183,7 +182,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, obj_desc->common_field.access_byte_width) { /* * This is the case where the access_type (acc_word, etc.) is wider - * than the region itself. For example, a region of length one + * than the region itself. For example, a region of length one * byte, and a field with Dword access specified. */ ACPI_ERROR((AE_INFO, @@ -321,7 +320,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, * * DESCRIPTION: Check if a value is out of range of the field being written. * Used to check if the values written to Index and Bank registers - * are out of range. Normally, the value is simply truncated + * are out of range. Normally, the value is simply truncated * to fit the field, but this case is most likely a serious * coding error in the ASL. * @@ -330,7 +329,6 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, static u8 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) { - ACPI_FUNCTION_NAME(ex_register_overflow); if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { /* @@ -370,7 +368,7 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) * * RETURN: Status * - * DESCRIPTION: Read or Write a single datum of a field. The field_type is + * DESCRIPTION: Read or Write a single datum of a field. The field_type is * demultiplexed here to handle the different types of fields * (buffer_field, region_field, index_field, bank_field) * @@ -860,7 +858,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); /* * We must have a buffer that is at least as long as the field - * we are writing to. This is because individual fields are + * we are writing to. This is because individual fields are * indivisible and partial writes are not supported -- as per * the ACPI specification. */ @@ -875,7 +873,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* * Copy the original data to the new buffer, starting - * at Byte zero. All unused (upper) bytes of the + * at Byte zero. All unused (upper) bytes of the * buffer will be 0. */ ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 271c0c57ea10..72a2a13b6d36 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -254,7 +253,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, ACPI_FUNCTION_TRACE(ex_do_concatenate); /* - * Convert the second operand if necessary. The first operand + * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand @@ -573,7 +572,7 @@ acpi_ex_do_logical_op(u16 opcode, ACPI_FUNCTION_TRACE(ex_do_logical_op); /* - * Convert the second operand if necessary. The first operand + * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI 3.0+ specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index bcceda5be9e3..7be0205ad067 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exmutex - ASL Mutex Acquire/Release functions @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -305,7 +304,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) ACPI_FUNCTION_TRACE(ex_release_mutex_object); if (obj_desc->mutex.acquisition_depth == 0) { - return (AE_NOT_ACQUIRED); + return_ACPI_STATUS(AE_NOT_ACQUIRED); } /* Match multiple Acquires with multiple Releases */ @@ -378,7 +377,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Must have a valid thread. */ + /* Must have a valid thread ID */ + if (!walk_state->thread) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", @@ -462,7 +462,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) union acpi_operand_object *next = thread->acquired_mutex_list; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_ENTRY(); + ACPI_FUNCTION_NAME(ex_release_all_mutexes); /* Traverse the list of owned mutexes, releasing each one */ @@ -474,6 +474,10 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) obj_desc->mutex.next = NULL; obj_desc->mutex.acquisition_depth = 0; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Force-releasing held mutex: %p\n", + obj_desc)); + /* Release the mutex, special case for Global Lock */ if (obj_desc == acpi_gbl_global_lock_mutex) { diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index fcc75fa27d32..14689dec4960 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exnames - interpreter/scanner name load/execute @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,8 +52,7 @@ ACPI_MODULE_NAME("exnames") /* Local prototypes */ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs); -static acpi_status -acpi_ex_name_segment(u8 ** in_aml_address, char *name_string); +static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string); /******************************************************************************* * @@ -64,7 +62,7 @@ acpi_ex_name_segment(u8 ** in_aml_address, char *name_string); * (-1)==root, 0==none * num_name_segs - count of 4-character name segments * - * RETURN: A pointer to the allocated string segment. This segment must + * RETURN: A pointer to the allocated string segment. This segment must * be deleted by the caller. * * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name @@ -178,7 +176,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); - for (index = 0; (index < ACPI_NAME_SIZE) + for (index = 0; + (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { char_buf[index] = *aml_address++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 9ba8c73cea16..b60c877f5906 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -606,7 +605,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) } /* - * Set result to ONES (TRUE) if Value == 0. Note: + * Set result to ONES (TRUE) if Value == 0. Note: * return_desc->Integer.Value is initially == 0 (FALSE) from above. */ if (!operand[0]->integer.value) { @@ -618,7 +617,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) case AML_INCREMENT_OP: /* Increment (Operand) */ /* - * Create a new integer. Can't just get the base integer and + * Create a new integer. Can't just get the base integer and * increment it because it may be an Arg or Field. */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); @@ -686,7 +685,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) /* * Note: The operand is not resolved at this point because we want to - * get the associated object, not its value. For example, we don't + * get the associated object, not its value. For example, we don't * want to resolve a field_unit to its value, we want the actual * field_unit object. */ @@ -727,7 +726,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) /* * The type of the base object must be integer, buffer, string, or - * package. All others are not supported. + * package. All others are not supported. * * NOTE: Integer is not specifically supported by the ACPI spec, * but is supported implicitly via implicit operand conversion. @@ -949,13 +948,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ return_desc = acpi_ut_create_integer_object((u64) - temp_desc-> - buffer. - pointer - [operand - [0]-> - reference. - value]); + temp_desc->buffer.pointer[operand[0]->reference.value]); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; @@ -965,7 +958,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) case ACPI_TYPE_PACKAGE: /* - * Return the referenced element of the package. We must + * Return the referenced element of the package. We must * add another reference to the referenced object, however. */ return_desc = diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index 879e8a277b94..e491e46f17df 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,7 +123,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method - * completes. The notify handlers are NOT invoked synchronously + * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 71fcc65c9ffa..2d7491f3126e 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exoparg3 - AML execution - opcodes with 3 arguments @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -158,7 +157,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ /* - * Create the return object. The Source operand is guaranteed to be + * Create the return object. The Source operand is guaranteed to be * either a String or a Buffer, so just use its type. */ return_desc = acpi_ut_create_internal_object((operand[0])-> diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 0786b8659061..b76b97002dff 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exoparg6 - AML execution - opcodes with 6 arguments @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -198,7 +197,7 @@ acpi_ex_do_match(u32 match_op, return (FALSE); } - return logical_result; + return (logical_result); } /******************************************************************************* @@ -269,7 +268,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) * and the next should be examined. * * Upon finding a match, the loop will terminate via "break" at - * the bottom. If it terminates "normally", match_value will be + * the bottom. If it terminates "normally", match_value will be * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no * match was found. */ diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 81eca60d2748..d6eab81f54fb 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -78,8 +77,8 @@ acpi_ex_generate_access(u32 field_bit_offset, * any_acc keyword. * * NOTE: Need to have the region_length in order to check for boundary - * conditions (end-of-region). However, the region_length is a deferred - * operation. Therefore, to complete this implementation, the generation + * conditions (end-of-region). However, the region_length is a deferred + * operation. Therefore, to complete this implementation, the generation * of this access width must be deferred until the region length has * been evaluated. * @@ -277,7 +276,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, /* Invalid field access type */ ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access)); - return_UINT32(0); + return_VALUE(0); } if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { @@ -290,7 +289,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, } *return_byte_alignment = byte_alignment; - return_UINT32(bit_length); + return_VALUE(bit_length); } /******************************************************************************* @@ -308,7 +307,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, * RETURN: Status * * DESCRIPTION: Initialize the areas of the field object that are common - * to the various types of fields. Note: This is very "sensitive" + * to the various types of fields. Note: This is very "sensitive" * code because we are solving the general case for field * alignment. * @@ -336,13 +335,13 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, obj_desc->common_field.bit_length = field_bit_length; /* - * Decode the access type so we can compute offsets. The access type gives + * Decode the access type so we can compute offsets. The access type gives * two pieces of information - the width of each field access and the * necessary byte_alignment (address granularity) of the access. * * For any_acc, the access_bit_width is the largest width that is both * necessary and possible in an attempt to access the whole field in one - * I/O operation. However, for any_acc, the byte_alignment is always one + * I/O operation. However, for any_acc, the byte_alignment is always one * byte. * * For all Buffer Fields, the byte_alignment is always one byte. @@ -363,7 +362,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, /* * base_byte_offset is the address of the start of the field within the - * region. It is the byte address of the first *datum* (field-width data + * region. It is the byte address of the first *datum* (field-width data * unit) of the field. (i.e., the first datum that contains at least the * first *bit* of the field.) * diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 1f1ce0c3d2f8..182abaf045e1 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exregion - ACPI default op_region (address space) handlers @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -143,9 +142,9 @@ acpi_ex_system_memory_space_handler(u32 function, } /* - * Attempt to map from the requested address to the end of the region. - * However, we will never map more than one page, nor will we cross - * a page boundary. + * October 2009: Attempt to map from the requested address to the + * end of the region. However, we will never map more than one + * page, nor will we cross a page boundary. */ map_length = (acpi_size) ((mem_info->address + mem_info->length) - address); @@ -155,12 +154,15 @@ acpi_ex_system_memory_space_handler(u32 function, * a page boundary, just map up to the page boundary, do not cross. * On some systems, crossing a page boundary while mapping regions * can cause warnings if the pages have different attributes - * due to resource management + * due to resource management. + * + * This has the added benefit of constraining a single mapping to + * one page, which is similar to the original code that used a 4k + * maximum window. */ page_boundary_map_length = ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address; - - if (!page_boundary_map_length) { + if (page_boundary_map_length == 0) { page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; } @@ -202,7 +204,7 @@ acpi_ex_system_memory_space_handler(u32 function, * Perform the memory read or write * * Note: For machines that do not support non-aligned transfers, the target - * address was checked for alignment above. We do not attempt to break the + * address was checked for alignment above. We do not attempt to break the * transfer up into smaller (byte-size) chunks because the AML specifically * asked for a transfer width that the hardware may require. */ @@ -237,19 +239,19 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: - ACPI_SET8(logical_addr_ptr) = (u8) * value; + ACPI_SET8(logical_addr_ptr, *value); break; case 16: - ACPI_SET16(logical_addr_ptr) = (u16) * value; + ACPI_SET16(logical_addr_ptr, *value); break; case 32: - ACPI_SET32(logical_addr_ptr) = (u32) * value; + ACPI_SET32(logical_addr_ptr, *value); break; case 64: - ACPI_SET64(logical_addr_ptr) = (u64) * value; + ACPI_SET64(logical_addr_ptr, *value); break; default: diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index fa50e77e64a8..8565b6bd12bb 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exresnte - AML Interpreter object resolution @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,8 +57,8 @@ ACPI_MODULE_NAME("exresnte") * PARAMETERS: object_ptr - Pointer to a location that contains * a pointer to a NS node, and will receive a * pointer to the resolved object. - * walk_state - Current state. Valid only if executing AML - * code. NULL if simply resolving an object + * walk_state - Current state. Valid only if executing AML + * code. NULL if simply resolving an object * * RETURN: Status * @@ -67,7 +66,7 @@ ACPI_MODULE_NAME("exresnte") * * Note: for some of the data types, the pointer attached to the Node * can be either a pointer to an actual internal object or a pointer into the - * AML stream itself. These types are currently: + * AML stream itself. These types are currently: * * ACPI_TYPE_INTEGER * ACPI_TYPE_STRING @@ -89,7 +88,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); /* - * The stack pointer points to a struct acpi_namespace_node (Node). Get the + * The stack pointer points to a struct acpi_namespace_node (Node). Get the * object that is attached to the Node. */ node = *object_ptr; diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index bbf40ac27585..e4f9dfbb2a13 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exresolv - AML Interpreter object resolution @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -327,7 +326,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, * * RETURN: Status * - * DESCRIPTION: Return the base object and type. Traverse a reference list if + * DESCRIPTION: Return the base object and type. Traverse a reference list if * necessary to get to the base object. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index f232fbabdea8..9fb9f5e9a4da 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exresop - AML Interpreter operand/object resolution @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,7 +86,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed, if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) { /* * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference - * objects and thus allow them to be targets. (As per the ACPI + * objects and thus allow them to be targets. (As per the ACPI * specification, a store to a constant is a noop.) */ if ((this_type == ACPI_TYPE_INTEGER) && @@ -337,7 +336,8 @@ acpi_ex_resolve_operands(u16 opcode, if ((opcode == AML_STORE_OP) && ((*stack_ptr)->common.type == ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { + && ((*stack_ptr)->reference.class == + ACPI_REFCLASS_INDEX)) { goto next_operand; } break; @@ -638,7 +638,7 @@ acpi_ex_resolve_operands(u16 opcode, if (acpi_gbl_enable_interpreter_slack) { /* * Enable original behavior of Store(), allowing any and all - * objects as the source operand. The ACPI spec does not + * objects as the source operand. The ACPI spec does not * allow this, however. */ break; diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 5fffe7ab5ece..93c6049c2d75 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -374,7 +374,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * with the input value. * * When storing into an object the data is converted to the - * target object type then stored in the object. This means + * target object type then stored in the object. This means * that the target object type (for an initialized target) will * not be changed by a store operation. * @@ -487,14 +487,33 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, default: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing %s (%p) directly into node (%p) with no implicit conversion\n", + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", acpi_ut_get_object_type_name(source_desc), - source_desc, node)); + source_desc, + acpi_ut_get_object_type_name(target_desc), + node)); - /* No conversions for all other types. Just attach the source object */ + /* + * No conversions for all other types. Directly store a copy of + * the source object. NOTE: This is a departure from the ACPI + * spec, which states "If conversion is impossible, abort the + * running control method". + * + * This code implements "If conversion is impossible, treat the + * Store operation as a CopyObject". + */ + status = + acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - status = acpi_ns_attach_object(node, source_desc, - source_desc->common.type); + status = + acpi_ns_attach_object(node, new_desc, + new_desc->common.type); + acpi_ut_remove_reference(new_desc); break; } diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index b35bed52e061..1cefe777068e 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exstoren - AML Interpreter object store support, @@ -7,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +60,7 @@ ACPI_MODULE_NAME("exstoren") * * RETURN: Status, resolved object in source_desc_ptr. * - * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * DESCRIPTION: Resolve an object. If the object is a reference, dereference * it and return the actual object in the source_desc_ptr. * ******************************************************************************/ @@ -93,7 +92,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, /* * Stores into a Field/Region or into a Integer/Buffer/String - * are all essentially the same. This case handles the + * are all essentially the same. This case handles the * "interchangeable" types Integer, String, and Buffer. */ if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { @@ -167,7 +166,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * * RETURN: Status * - * DESCRIPTION: "Store" an object to another object. This may include + * DESCRIPTION: "Store" an object to another object. This may include * converting the source type to the target type (implicit * conversion), and a copy of the value of the source to * the target. @@ -178,14 +177,14 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * with the input value. * * When storing into an object the data is converted to the - * target object type then stored in the object. This means + * target object type then stored in the object. This means * that the target object type (for an initialized target) will * not be changed by a store operation. * * This module allows destination types of Number, String, * Buffer, and Package. * - * Assumes parameters are already validated. NOTE: source_desc + * Assumes parameters are already validated. NOTE: source_desc * resolution (from a reference object) must be performed by * the caller if necessary. * @@ -254,7 +253,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, /* Truncate value if we are executing from a 32-bit ACPI table */ - acpi_ex_truncate_for32bit_table(dest_desc); + (void)acpi_ex_truncate_for32bit_table(dest_desc); break; case ACPI_TYPE_STRING: diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index 53c248473547..26e371073b1a 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exstorob - AML Interpreter object store support, store to object @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +107,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, #ifdef ACPI_OBSOLETE_BEHAVIOR /* * NOTE: ACPI versions up to 3.0 specified that the buffer must be - * truncated if the string is smaller than the buffer. However, "other" + * truncated if the string is smaller than the buffer. However, "other" * implementations of ACPI never did this and thus became the defacto * standard. ACPI 3.0A changes this behavior such that the buffer * is no longer truncated. @@ -117,7 +116,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, /* * OBSOLETE BEHAVIOR: * If the original source was a string, we must truncate the buffer, - * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer + * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer * copy must not truncate the original buffer. */ if (original_src_type == ACPI_TYPE_STRING) { diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index b760641e2fc6..6578dee2e51b 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exsystem - Interface to OS services @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,7 +58,7 @@ ACPI_MODULE_NAME("exsystem") * RETURN: Status * * DESCRIPTION: Implements a semaphore wait with a check to see if the - * semaphore is available immediately. If it is not, the + * semaphore is available immediately. If it is not, the * interpreter is released before waiting. * ******************************************************************************/ @@ -104,7 +103,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) * RETURN: Status * * DESCRIPTION: Implements a mutex wait with a check to see if the - * mutex is available immediately. If it is not, the + * mutex is available immediately. If it is not, the * interpreter is released before waiting. * ******************************************************************************/ @@ -152,7 +151,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) * DESCRIPTION: Suspend running thread for specified amount of time. * Note: ACPI specification requires that Stall() does not * relinquish the processor, and delays longer than 100 usec - * should use Sleep() instead. We allow stalls up to 255 usec + * should use Sleep() instead. We allow stalls up to 255 usec * for compatibility with other interpreters and existing BIOSs. * ******************************************************************************/ @@ -254,7 +253,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) * RETURN: Status * * DESCRIPTION: Provides an access point to perform synchronization operations - * within the AML. This operation is a request to wait for an + * within the AML. This operation is a request to wait for an * event. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index d1ab7917eed7..b205cbb4b50c 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: exutils - interpreter/scanner utilities @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,12 +44,12 @@ /* * DEFINE_AML_GLOBALS is tested in amlcode.h * to determine whether certain global names should be "defined" or only - * "declared" in the current compilation. This enhances maintainability + * "declared" in the current compilation. This enhances maintainability * by enabling a single header file to embody all knowledge of the names * in question. * * Exactly one module of any executable should #define DEFINE_GLOBALS - * before #including the header files which use this convention. The + * before #including the header files which use this convention. The * names in question will be defined and initialized in that module, * and declared as extern in all other modules which #include those * header files. @@ -203,35 +202,39 @@ void acpi_ex_relinquish_interpreter(void) * * PARAMETERS: obj_desc - Object to be truncated * - * RETURN: none + * RETURN: TRUE if a truncation was performed, FALSE otherwise. * * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is * 32-bit, as determined by the revision of the DSDT. * ******************************************************************************/ -void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) +u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) { ACPI_FUNCTION_ENTRY(); /* * Object must be a valid number and we must be executing - * a control method. NS node could be there for AML_INT_NAMEPATH_OP. + * a control method. Object could be NS node for AML_INT_NAMEPATH_OP. */ if ((!obj_desc) || (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { - return; + return (FALSE); } - if (acpi_gbl_integer_byte_width == 4) { + if ((acpi_gbl_integer_byte_width == 4) && + (obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) { /* - * We are running a method that exists in a 32-bit ACPI table. + * We are executing in a 32-bit ACPI table. * Truncate the value to 32 bits by zeroing out the upper 32-bit field */ - obj_desc->integer.value &= (u64) ACPI_UINT32_MAX; + obj_desc->integer.value &= (u64)ACPI_UINT32_MAX; + return (TRUE); } + + return (FALSE); } /******************************************************************************* @@ -337,7 +340,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base) /* u64 is unsigned, so we don't worry about a '-' prefix */ if (value == 0) { - return_UINT32(1); + return_VALUE(1); } current_value = value; @@ -351,7 +354,7 @@ static u32 acpi_ex_digits_needed(u64 value, u32 base) num_digits++; } - return_UINT32(num_digits); + return_VALUE(num_digits); } /******************************************************************************* diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index a1e71d0ef57b..deb3f61e2bd1 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,8 +108,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * enable bits to default */ status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, - (u32) acpi_gbl_FADT.acpi_disable, - 8); + (u32)acpi_gbl_FADT.acpi_disable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable Legacy (non-ACPI) mode\n")); break; @@ -136,7 +134,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY * - * DESCRIPTION: Return current operating state of system. Determined by + * DESCRIPTION: Return current operating state of system. Determined by * querying the SCI_EN bit. * ******************************************************************************/ @@ -153,18 +151,18 @@ u32 acpi_hw_get_mode(void) * system does not support mode transition. */ if (!acpi_gbl_FADT.smi_command) { - return_UINT32(ACPI_SYS_MODE_ACPI); + return_VALUE(ACPI_SYS_MODE_ACPI); } status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); if (ACPI_FAILURE(status)) { - return_UINT32(ACPI_SYS_MODE_LEGACY); + return_VALUE(ACPI_SYS_MODE_LEGACY); } if (value) { - return_UINT32(ACPI_SYS_MODE_ACPI); + return_VALUE(ACPI_SYS_MODE_ACPI); } else { - return_UINT32(ACPI_SYS_MODE_LEGACY); + return_VALUE(ACPI_SYS_MODE_LEGACY); } } diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 94996f9ae3ad..5e5f76230f5e 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -200,7 +200,6 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) * FUNCTION: acpi_hw_extended_wake * * PARAMETERS: sleep_state - Which sleep state we just exited - * flags - Reserved, set to zero * * RETURN: Status * diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index db4076580e2b..20d02e93c990 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwgpe - Low level GPE enable/disable/clear functions @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,8 +69,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) { - return (u32)1 << (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number); + + return ((u32)1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); } /****************************************************************************** @@ -134,7 +135,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) break; default: - ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u\n", action)); + ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action)); return (AE_BAD_PARAMETER); } @@ -339,7 +340,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, acpi_status acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, - struct acpi_gpe_block_info *gpe_block, void *context) + struct acpi_gpe_block_info * gpe_block, + void *context) { u32 i; acpi_status status; diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index 1455ddcdc32c..0889a629505f 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -259,7 +259,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, status = acpi_hw_get_pci_device_info(pci_id, info->device, &bus_number, &is_bridge); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + return (status); } info = info->next; @@ -271,7 +271,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, status, bus_number, is_bridge)); - return_ACPI_STATUS(AE_OK); + return (AE_OK); } /******************************************************************************* diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 4af6d20ef077..083d6551f0e2 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -1,4 +1,3 @@ - /******************************************************************************* * * Module Name: hwregs - Read/write access functions for the various ACPI @@ -7,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +44,6 @@ #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #include "acevents.h" #define _COMPONENT ACPI_HARDWARE @@ -365,8 +363,7 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) * DESCRIPTION: Read from the specified ACPI register * ******************************************************************************/ -acpi_status -acpi_hw_register_read(u32 register_id, u32 * return_value) +acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) { u32 value = 0; acpi_status status; @@ -486,7 +483,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ status = acpi_hw_write_multiple(value, &acpi_gbl_xpm1a_enable, diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 3fddde056a5e..e3828cc4361b 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@ #include <acpi/acpi.h> #include <linux/acpi.h> #include "accommon.h" -#include <linux/module.h> #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwsleep") @@ -178,7 +177,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) * to still read the right value. Ideally, this block would go * away entirely. */ - acpi_os_stall(10000000); + acpi_os_stall(10 * ACPI_USEC_PER_SEC); status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, sleep_enable_reg_info-> @@ -323,7 +322,8 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state) * and use it to determine whether the system is rebooting or * resuming. Clear WAK_STS for compatibility. */ - acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); + (void)acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, + ACPI_CLEAR_STATUS); acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index b6411f16832f..0c1a8bbd05d6 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Name: hwtimer.c - ACPI Power Management Timer Interface @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -101,8 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks) return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = - acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); return_ACPI_STATUS(status); } @@ -129,7 +127,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer) * a versatile and accurate timer. * * Note that this function accommodates only a single timer - * rollover. Thus for 24-bit timers, this function should only + * rollover. Thus for 24-bit timers, this function should only * be used for calculating durations less than ~4.6 seconds * (~20 minutes for 32-bit timers) -- calculations below: * @@ -178,10 +176,11 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) /* * Compute Duration (Requires a 64-bit multiply and divide): * - * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY; + * time_elapsed (microseconds) = + * (delta_ticks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; */ - status = acpi_ut_short_divide(((u64) delta_ticks) * 1000000, - PM_TIMER_FREQUENCY, "ient, NULL); + status = acpi_ut_short_divide(((u64)delta_ticks) * ACPI_USEC_PER_SEC, + ACPI_PM_TIMER_FREQUENCY, "ient, NULL); *time_elapsed = (u32) quotient; return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index c99d546b217f..eab70d58852a 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwvalid - I/O request validation @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,7 +135,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { ACPI_ERROR((AE_INFO, "Bad BitWidth parameter: %8.8X", bit_width)); - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } port_info = acpi_protected_ports; @@ -235,11 +234,11 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) status = acpi_hw_validate_io_request(address, width); if (ACPI_SUCCESS(status)) { status = acpi_os_read_port(address, value, width); - return status; + return (status); } if (status != AE_AML_ILLEGAL_ADDRESS) { - return status; + return (status); } /* @@ -254,7 +253,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) if (acpi_hw_validate_io_request(address, 8) == AE_OK) { status = acpi_os_read_port(address, &one_byte, 8); if (ACPI_FAILURE(status)) { - return status; + return (status); } *value |= (one_byte << i); @@ -263,7 +262,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) address++; } - return AE_OK; + return (AE_OK); } /****************************************************************************** @@ -298,11 +297,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) status = acpi_hw_validate_io_request(address, width); if (ACPI_SUCCESS(status)) { status = acpi_os_write_port(address, value, width); - return status; + return (status); } if (status != AE_AML_ILLEGAL_ADDRESS) { - return status; + return (status); } /* @@ -318,12 +317,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) status = acpi_os_write_port(address, (value >> i) & 0xFF, 8); if (ACPI_FAILURE(status)) { - return status; + return (status); } } address++; } - return AE_OK; + return (AE_OK); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 7bfd649d1996..04c2e16f2c0a 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -1,4 +1,3 @@ - /****************************************************************************** * * Module Name: hwxface - Public ACPICA hardware interfaces @@ -6,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,10 +80,10 @@ acpi_status acpi_reset(void) if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { /* - * For I/O space, write directly to the OSL. This - * bypasses the port validation mechanism, which may - * block a valid write to the reset register. Spec - * section 4.7.3.6 requires register width to be 8. + * For I/O space, write directly to the OSL. This bypasses the port + * validation mechanism, which may block a valid write to the reset + * register. + * Spec section 4.7.3.6 requires register width to be 8. */ status = acpi_os_write_port((acpi_io_address) reset_reg->address, @@ -334,7 +333,7 @@ ACPI_EXPORT_SYMBOL(acpi_read_bit_register) * FUNCTION: acpi_write_bit_register * * PARAMETERS: register_id - ID of ACPI Bit Register to access - * Value - Value to write to the register, in bit + * value - Value to write to the register, in bit * position zero. The bit is automatically * shifted to the correct position. * @@ -441,17 +440,41 @@ ACPI_EXPORT_SYMBOL(acpi_write_bit_register) * *sleep_type_a - Where SLP_TYPa is returned * *sleep_type_b - Where SLP_TYPb is returned * - * RETURN: status - ACPI status + * RETURN: Status + * + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested + * sleep state via the appropriate \_Sx object. + * + * The sleep state package returned from the corresponding \_Sx_ object + * must contain at least one integer. * - * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep - * state. + * March 2005: + * Added support for a package that contains two integers. This + * goes against the ACPI specification which defines this object as a + * package with one encoded DWORD integer. However, existing practice + * by many BIOS vendors is to return a package with 2 or more integer + * elements, at least one per sleep type (A/B). + * + * January 2013: + * Therefore, we must be prepared to accept a package with either a + * single integer or multiple integers. + * + * The single integer DWORD format is as follows: + * BYTE 0 - Value for the PM1A SLP_TYP register + * BYTE 1 - Value for the PM1B SLP_TYP register + * BYTE 2-3 - Reserved + * + * The dual integer format is as follows: + * Integer 0 - Value for the PM1A SLP_TYP register + * Integer 1 - Value for the PM1A SLP_TYP register * ******************************************************************************/ acpi_status acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) { - acpi_status status = AE_OK; + acpi_status status; struct acpi_evaluate_info *info; + union acpi_operand_object **elements; ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); @@ -468,18 +491,14 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) return_ACPI_STATUS(AE_NO_MEMORY); } + /* + * Evaluate the \_Sx namespace object containing the register values + * for this state + */ info->pathname = ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); - - /* Evaluate the namespace object containing the values for this state */ - status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s while evaluating SleepState [%s]\n", - acpi_format_exception(status), - info->pathname)); - goto cleanup; } @@ -488,64 +507,67 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) if (!info->return_object) { ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", info->pathname)); - status = AE_NOT_EXIST; + status = AE_AML_NO_RETURN_VALUE; + goto cleanup; } - /* It must be of type Package */ + /* Return object must be of type Package */ - else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { + if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; + goto cleanup1; } /* - * The package must have at least two elements. NOTE (March 2005): This - * goes against the current ACPI spec which defines this object as a - * package with one encoded DWORD element. However, existing practice - * by BIOS vendors seems to be to have 2 or more elements, at least - * one per sleep type (A/B). + * Any warnings about the package length or the object types have + * already been issued by the predefined name module -- there is no + * need to repeat them here. */ - else if (info->return_object->package.count < 2) { - ACPI_ERROR((AE_INFO, - "Sleep State return package does not have at least two elements")); - status = AE_AML_NO_OPERAND; - } + elements = info->return_object->package.elements; + switch (info->return_object->package.count) { + case 0: + status = AE_AML_PACKAGE_LIMIT; + break; + + case 1: + if (elements[0]->common.type != ACPI_TYPE_INTEGER) { + status = AE_AML_OPERAND_TYPE; + break; + } - /* The first two elements must both be of type Integer */ + /* A valid _Sx_ package with one integer */ - else if (((info->return_object->package.elements[0])->common.type - != ACPI_TYPE_INTEGER) || - ((info->return_object->package.elements[1])->common.type - != ACPI_TYPE_INTEGER)) { - ACPI_ERROR((AE_INFO, - "Sleep State return package elements are not both Integers " - "(%s, %s)", - acpi_ut_get_object_type_name(info->return_object-> - package.elements[0]), - acpi_ut_get_object_type_name(info->return_object-> - package.elements[1]))); - status = AE_AML_OPERAND_TYPE; - } else { - /* Valid _Sx_ package size, type, and value */ + *sleep_type_a = (u8)elements[0]->integer.value; + *sleep_type_b = (u8)(elements[0]->integer.value >> 8); + break; - *sleep_type_a = (u8) - (info->return_object->package.elements[0])->integer.value; - *sleep_type_b = (u8) - (info->return_object->package.elements[1])->integer.value; - } + case 2: + default: + if ((elements[0]->common.type != ACPI_TYPE_INTEGER) || + (elements[1]->common.type != ACPI_TYPE_INTEGER)) { + status = AE_AML_OPERAND_TYPE; + break; + } - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "While evaluating SleepState [%s], bad Sleep object %p type %s", - info->pathname, info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); + /* A valid _Sx_ package with two integers */ + + *sleep_type_a = (u8)elements[0]->integer.value; + *sleep_type_b = (u8)elements[1]->integer.value; + break; } + cleanup1: acpi_ut_remove_reference(info->return_object); cleanup: + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While evaluating Sleep State [%s]", + info->pathname)); + } + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 0ff1ecea5c3a..35eebdac0f9d 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,16 +41,15 @@ * POSSIBILITY OF SUCH DAMAGES. */ +#include <linux/export.h> #include <acpi/acpi.h> #include "accommon.h" -#include <linux/module.h> #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwxfsleep") /* Local prototypes */ -static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); +static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); /* * Dispatch table used to efficiently branch to the various sleep @@ -208,7 +207,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) (u32)acpi_gbl_FADT.s4_bios_request, 8); do { - acpi_os_stall(1000); + acpi_os_stall(ACPI_USEC_PER_MSEC); status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { @@ -234,8 +233,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) * function. * ******************************************************************************/ -static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) +static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) { acpi_status status; struct acpi_sleep_functions *sleep_functions = @@ -352,7 +350,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) * * RETURN: Status * - * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * DESCRIPTION: Enter a system sleep state * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ @@ -369,8 +367,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } - status = - acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID); + status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID); return_ACPI_STATUS(status); } @@ -385,8 +382,9 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) * RETURN: Status * * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a - * sleep. - * Called with interrupts DISABLED. + * sleep. Called with interrupts DISABLED. + * We break wake/resume into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. * ******************************************************************************/ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) @@ -396,8 +394,7 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); status = - acpi_hw_sleep_dispatch(sleep_state, - ACPI_WAKE_PREP_FUNCTION_ID); + acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 23db53ce2293..8769cf83b044 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,11 +110,11 @@ acpi_status acpi_ns_root_initialize(void) status = acpi_ns_lookup(NULL, init_val->name, init_val->type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node); - - if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */ + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not create predefined name %s", init_val->name)); + continue; } /* @@ -179,8 +179,7 @@ acpi_status acpi_ns_root_initialize(void) /* Build an object around the static string */ - obj_desc->string.length = - (u32) ACPI_STRLEN(val); + obj_desc->string.length = (u32)ACPI_STRLEN(val); obj_desc->string.pointer = val; obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; break; diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index ac389e5bb594..243737363fb8 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -332,7 +332,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) * * RETURN: None. * - * DESCRIPTION: Delete a subtree of the namespace. This includes all objects + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects * stored within the subtree. * ******************************************************************************/ @@ -418,7 +418,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) * RETURN: Status * * DESCRIPTION: Delete entries within the namespace that are owned by a - * specific ID. Used to delete entire ACPI tables. All + * specific ID. Used to delete entire ACPI tables. All * reference counts are updated. * * MUTEX: Locks namespace during deletion walk. diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 2526aaf945ee..ce6e97326205 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" +#include <acpi/acoutput.h> #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsdump") @@ -77,8 +78,9 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) ACPI_FUNCTION_NAME(ns_print_pathname); - if (!(acpi_dbg_level & ACPI_LV_NAMES) - || !(acpi_dbg_layer & ACPI_NAMESPACE)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_NAMES, ACPI_NAMESPACE)) { return; } @@ -127,7 +129,7 @@ acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) /* Do this only if the requested debug level and component are enabled */ - if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) { + if (!ACPI_IS_DEBUG_ENABLED(level, component)) { return_VOID; } @@ -209,14 +211,6 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, "Invalid ACPI Object Type 0x%08X", type)); } - if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { - this_node->name.integer = - acpi_ut_repair_name(this_node->name.ascii); - - ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", - this_node->name.integer)); - } - acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); } @@ -700,7 +694,7 @@ void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level) * * PARAMETERS: search_base - Root of subtree to be dumped, or * NS_ALL to dump the entire namespace - * max_depth - Maximum depth of dump. Use INT_MAX + * max_depth - Maximum depth of dump. Use INT_MAX * for an effectively unlimited depth. * * RETURN: None @@ -737,5 +731,5 @@ void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth) ACPI_OWNER_ID_MAX, search_handle); return_VOID; } -#endif /* _ACPI_ASL_COMPILER */ -#endif /* defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) */ +#endif +#endif diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 944d4c8d9438..409ae80824d1 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,6 @@ */ #include <acpi/acpi.h> -#include "accommon.h" /* TBD: This entire module is apparently obsolete and should be removed */ diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 69074be498e8..1538f3eb2a8f 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 95ffe8dfa1f1..2a431ec50a25 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,7 +46,6 @@ #include "acnamesp.h" #include "acdispat.h" #include "acinterp.h" -#include <linux/nmi.h> #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsinit") @@ -87,7 +86,7 @@ acpi_status acpi_ns_initialize_objects(void) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Completing Region/Field/Buffer/Package initialization:")); + "Completing Region/Field/Buffer/Package initialization:\n")); /* Set all init info to zero */ @@ -96,14 +95,14 @@ acpi_status acpi_ns_initialize_objects(void) /* Walk entire namespace from the supplied root */ status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL, - &info, NULL); + ACPI_UINT32_MAX, acpi_ns_init_one_object, + NULL, &info, NULL); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nInitialized %u/%u Regions %u/%u Fields %u/%u " + " Initialized %u/%u Regions %u/%u Fields %u/%u " "Buffers %u/%u Packages (%u nodes)\n", info.op_region_init, info.op_region_count, info.field_init, info.field_count, @@ -150,7 +149,7 @@ acpi_status acpi_ns_initialize_devices(void) ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Initializing Device/Processor/Thermal objects " - "by executing _INI methods:")); + "and executing _INI/_STA methods:\n")); /* Tree analysis: find all subtrees that contain _INI methods */ @@ -208,7 +207,7 @@ acpi_status acpi_ns_initialize_devices(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nExecuted %u _INI methods requiring %u _STA executions " + " Executed %u _INI methods requiring %u _STA executions " "(examined %u objects)\n", info.num_INI, info.num_STA, info.device_count)); @@ -350,14 +349,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, } /* - * Print a dot for each object unless we are going to print the entire - * pathname - */ - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - - /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ @@ -572,20 +563,10 @@ acpi_ns_init_one_device(acpi_handle obj_handle, info->parameters = NULL; info->flags = ACPI_IGNORE_RETURN_VALUE; - /* - * Some hardware relies on this being executed as atomically - * as possible (without an NMI being received in the middle of - * this) - so disable NMIs and initialize the device: - */ status = acpi_ns_evaluate(info); if (ACPI_SUCCESS(status)) { walk_info->num_INI++; - - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && - (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } } #ifdef ACPI_DEBUG_OUTPUT else if (status != AE_NOT_FOUND) { diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 76935ff29289..0a7badc3179f 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,8 +80,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) /* * Parse the table and load the namespace with all named - * objects found within. Control methods are NOT parsed - * at this time. In fact, the control methods cannot be + * objects found within. Control methods are NOT parsed + * at this time. In fact, the control methods cannot be * parsed until the entire namespace is loaded, because * if a control method makes a forward reference (call) * to another control method, we can't continue parsing @@ -122,7 +122,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) } /* - * Now we can parse the control methods. We always parse + * Now we can parse the control methods. We always parse * them here for a sanity check, and if configured for * just-in-time parsing, we delete the control method * parse trees. @@ -166,7 +166,7 @@ acpi_status acpi_ns_load_namespace(void) } /* - * Load the namespace. The DSDT is required, + * Load the namespace. The DSDT is required, * but the SSDT and PSDT tables are optional. */ status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); @@ -283,7 +283,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) * RETURN: Status * * DESCRIPTION: Shrinks the namespace, typically in response to an undocking - * event. Deletes an entire subtree starting from (and + * event. Deletes an entire subtree starting from (and * including) the given handle. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index 96e0eb609bb4..90a0380fb8a0 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -126,7 +126,8 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, * the node, In external format (name segments separated by path * separators.) * - * DESCRIPTION: Used for debug printing in acpi_ns_search_table(). + * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually + * for error and debug statements. * ******************************************************************************/ @@ -195,7 +196,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) ACPI_ERROR((AE_INFO, "Invalid Namespace Node (%p) while traversing namespace", next_node)); - return 0; + return (0); } size += ACPI_PATH_SEGMENT_LENGTH; next_node = next_node->parent; diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index d6c9a3cc6716..7a736f4d1fd8 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,7 @@ ACPI_MODULE_NAME("nsobject") * RETURN: Status * * DESCRIPTION: Record the given object as the value associated with the - * name whose acpi_handle is passed. If Object is NULL + * name whose acpi_handle is passed. If Object is NULL * and Type is ACPI_TYPE_ANY, set the name as having no value. * Note: Future may require that the Node->Flags field be passed * as a parameter. @@ -133,7 +133,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node, ((struct acpi_namespace_node *)object)->object) { /* * Value passed is a name handle and that name has a - * non-null value. Use that name's value and type. + * non-null value. Use that name's value and type. */ obj_desc = ((struct acpi_namespace_node *)object)->object; object_type = ((struct acpi_namespace_node *)object)->type; @@ -321,7 +321,7 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union * * RETURN: Status * - * DESCRIPTION: Low-level attach data. Create and attach a Data object. + * DESCRIPTION: Low-level attach data. Create and attach a Data object. * ******************************************************************************/ @@ -377,7 +377,7 @@ acpi_ns_attach_data(struct acpi_namespace_node *node, * * RETURN: Status * - * DESCRIPTION: Low-level detach data. Delete the data node, but the caller + * DESCRIPTION: Low-level detach data. Delete the data node, but the caller * is responsible for the actual data. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index ec7ba2d3463c..35dde8151c0d 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -168,11 +168,11 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) /* * AML Parse, pass 1 * - * In this pass, we load most of the namespace. Control methods - * are not parsed until later. A parse tree is not created. Instead, - * each Parser Op subtree is deleted when it is finished. This saves + * In this pass, we load most of the namespace. Control methods + * are not parsed until later. A parse tree is not created. Instead, + * each Parser Op subtree is deleted when it is finished. This saves * a great deal of memory, and allows a small cache of parse objects - * to service the entire parse. The second pass of the parse then + * to service the entire parse. The second pass of the parse then * performs another complete parse of the AML. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 2419f417ea33..224c30053401 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -1,12 +1,11 @@ /****************************************************************************** * * Module Name: nspredef - Validation of ACPI predefined methods and objects - * $Revision: 1.1 $ * *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -74,27 +73,6 @@ ACPI_MODULE_NAME("nspredef") ******************************************************************************/ /* Local prototypes */ static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count); - -static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, - union acpi_operand_object **elements, - u8 type1, - u32 count1, - u8 type2, u32 count2, u32 start_index); - -static acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr, - u32 expected_btypes, u32 package_index); - -static acpi_status acpi_ns_check_reference(struct acpi_predefined_data *data, union acpi_operand_object *return_object); @@ -148,7 +126,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, pathname = acpi_ns_get_external_pathname(node); if (!pathname) { - return AE_OK; /* Could not get pathname, ignore */ + return (AE_OK); /* Could not get pathname, ignore */ } /* @@ -408,564 +386,6 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct /******************************************************************************* * - * FUNCTION: acpi_ns_check_package - * - * PARAMETERS: data - Pointer to validation data structure - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * - * RETURN: Status - * - * DESCRIPTION: Check a returned package object for the correct count and - * correct type of all sub-objects. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr) -{ - union acpi_operand_object *return_object = *return_object_ptr; - const union acpi_predefined_info *package; - union acpi_operand_object **elements; - acpi_status status = AE_OK; - u32 expected_count; - u32 count; - u32 i; - - ACPI_FUNCTION_NAME(ns_check_package); - - /* The package info for this name is in the next table entry */ - - package = data->predefined + 1; - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "%s Validating return Package of Type %X, Count %X\n", - data->pathname, package->ret_info.type, - return_object->package.count)); - - /* - * For variable-length Packages, we can safely remove all embedded - * and trailing NULL package elements - */ - acpi_ns_remove_null_elements(data, package->ret_info.type, - return_object); - - /* Extract package count and elements array */ - - elements = return_object->package.elements; - count = return_object->package.count; - - /* The package must have at least one element, else invalid */ - - if (!count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package has no elements (empty)")); - - return (AE_AML_OPERAND_VALUE); - } - - /* - * Decode the type of the expected package contents - * - * PTYPE1 packages contain no subpackages - * PTYPE2 packages contain sub-packages - */ - switch (package->ret_info.type) { - case ACPI_PTYPE1_FIXED: - - /* - * The package count is fixed and there are no sub-packages - * - * If package is too small, exit. - * If package is larger than expected, issue warning but continue - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (count < expected_count) { - goto package_too_small; - } else if (count > expected_count) { - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, - "%s: Return Package is larger than needed - " - "found %u, expected %u\n", - data->pathname, count, - expected_count)); - } - - /* Validate all elements of the returned package */ - - status = acpi_ns_check_package_elements(data, elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - break; - - case ACPI_PTYPE1_VAR: - - /* - * The package count is variable, there are no sub-packages, and all - * elements must be of the same type - */ - for (i = 0; i < count; i++) { - status = acpi_ns_check_object_type(data, elements, - package->ret_info. - object_type1, i); - if (ACPI_FAILURE(status)) { - return (status); - } - elements++; - } - break; - - case ACPI_PTYPE1_OPTION: - - /* - * The package count is variable, there are no sub-packages. There are - * a fixed number of required elements, and a variable number of - * optional elements. - * - * Check if package is at least as large as the minimum required - */ - expected_count = package->ret_info3.count; - if (count < expected_count) { - goto package_too_small; - } - - /* Variable number of sub-objects */ - - for (i = 0; i < count; i++) { - if (i < package->ret_info3.count) { - - /* These are the required package elements (0, 1, or 2) */ - - status = - acpi_ns_check_object_type(data, elements, - package-> - ret_info3. - object_type[i], - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } else { - /* These are the optional package elements */ - - status = - acpi_ns_check_object_type(data, elements, - package-> - ret_info3. - tail_object_type, - i); - if (ACPI_FAILURE(status)) { - return (status); - } - } - elements++; - } - break; - - case ACPI_PTYPE2_REV_FIXED: - - /* First element is the (Integer) revision */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - elements++; - count--; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - case ACPI_PTYPE2_PKG_COUNT: - - /* First element is the (Integer) count of sub-packages to follow */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Count cannot be larger than the parent package length, but allow it - * to be smaller. The >= accounts for the Integer above. - */ - expected_count = (u32) (*elements)->integer.value; - if (expected_count >= count) { - goto package_too_small; - } - - count = expected_count; - elements++; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - case ACPI_PTYPE2: - case ACPI_PTYPE2_FIXED: - case ACPI_PTYPE2_MIN: - case ACPI_PTYPE2_COUNT: - case ACPI_PTYPE2_FIX_VAR: - - /* - * These types all return a single Package that consists of a - * variable number of sub-Packages. - * - * First, ensure that the first element is a sub-Package. If not, - * the BIOS may have incorrectly returned the object as a single - * package instead of a Package of Packages (a common error if - * there is only one entry). We may be able to repair this by - * wrapping the returned Package with a new outer Package. - */ - if (*elements - && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { - - /* Create the new outer package and populate it */ - - status = - acpi_ns_wrap_with_package(data, return_object, - return_object_ptr); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Update locals to point to the new package (of 1 element) */ - - return_object = *return_object_ptr; - elements = return_object->package.elements; - count = 1; - } - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - default: - - /* Should not get here if predefined info table is correct */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Invalid internal return type in table entry: %X", - package->ret_info.type)); - - return (AE_AML_INTERNAL); - } - - return (status); - -package_too_small: - - /* Error exit for the case with an incorrect package count */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package is too small - found %u elements, expected %u", - count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_list - * - * PARAMETERS: data - Pointer to validation data structure - * package - Pointer to package-specific info for method - * elements - Element list of parent package. All elements - * of this list should be of type Package. - * count - Count of subpackages - * - * RETURN: Status - * - * DESCRIPTION: Examine a list of subpackages - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count) -{ - union acpi_operand_object *sub_package; - union acpi_operand_object **sub_elements; - acpi_status status; - u32 expected_count; - u32 i; - u32 j; - - /* - * Validate each sub-Package in the parent Package - * - * NOTE: assumes list of sub-packages contains no NULL elements. - * Any NULL elements should have been removed by earlier call - * to acpi_ns_remove_null_elements. - */ - for (i = 0; i < count; i++) { - sub_package = *elements; - sub_elements = sub_package->package.elements; - data->parent_package = sub_package; - - /* Each sub-object must be of type Package */ - - status = acpi_ns_check_object_type(data, &sub_package, - ACPI_RTYPE_PACKAGE, i); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Examine the different types of expected sub-packages */ - - data->parent_package = sub_package; - switch (package->ret_info.type) { - case ACPI_PTYPE2: - case ACPI_PTYPE2_PKG_COUNT: - case ACPI_PTYPE2_REV_FIXED: - - /* Each subpackage has a fixed number of elements */ - - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIX_VAR: - /* - * Each subpackage has a fixed number of elements and an - * optional element - */ - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - sub_package->package. - count - - package->ret_info. - count1, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_FIXED: - - /* Each sub-package has a fixed length */ - - expected_count = package->ret_info2.count; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - for (j = 0; j < expected_count; j++) { - status = - acpi_ns_check_object_type(data, - &sub_elements[j], - package-> - ret_info2. - object_type[j], - j); - if (ACPI_FAILURE(status)) { - return (status); - } - } - break; - - case ACPI_PTYPE2_MIN: - - /* Each sub-package has a variable but minimum length */ - - expected_count = package->ret_info.count1; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - sub_package->package. - count, 0, 0, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - case ACPI_PTYPE2_COUNT: - - /* - * First element is the (Integer) count of elements, including - * the count field (the ACPI name is num_elements) - */ - status = acpi_ns_check_object_type(data, sub_elements, - ACPI_RTYPE_INTEGER, - 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Make sure package is large enough for the Count and is - * is as large as the minimum size - */ - expected_count = (u32)(*sub_elements)->integer.value; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - if (sub_package->package.count < - package->ret_info.count1) { - expected_count = package->ret_info.count1; - goto package_too_small; - } - if (expected_count == 0) { - /* - * Either the num_entries element was originally zero or it was - * a NULL element and repaired to an Integer of value zero. - * In either case, repair it by setting num_entries to be the - * actual size of the subpackage. - */ - expected_count = sub_package->package.count; - (*sub_elements)->integer.value = expected_count; - } - - /* Check the type of each sub-package element */ - - status = - acpi_ns_check_package_elements(data, - (sub_elements + 1), - package->ret_info. - object_type1, - (expected_count - 1), - 0, 0, 1); - if (ACPI_FAILURE(status)) { - return (status); - } - break; - - default: /* Should not get here, type was validated by caller */ - - return (AE_AML_INTERNAL); - } - - elements++; - } - - return (AE_OK); - -package_too_small: - - /* The sub-package count was smaller than required */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Sub-Package[%u] is too small - found %u elements, expected %u", - i, sub_package->package.count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_elements - * - * PARAMETERS: data - Pointer to validation data structure - * elements - Pointer to the package elements array - * type1 - Object type for first group - * count1 - Count for first group - * type2 - Object type for second group - * count2 - Count for second group - * start_index - Start of the first group of elements - * - * RETURN: Status - * - * DESCRIPTION: Check that all elements of a package are of the correct object - * type. Supports up to two groups of different object types. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, - union acpi_operand_object **elements, - u8 type1, - u32 count1, - u8 type2, u32 count2, u32 start_index) -{ - union acpi_operand_object **this_element = elements; - acpi_status status; - u32 i; - - /* - * Up to two groups of package elements are supported by the data - * structure. All elements in each group must be of the same type. - * The second group can have a count of zero. - */ - for (i = 0; i < count1; i++) { - status = acpi_ns_check_object_type(data, this_element, - type1, i + start_index); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - for (i = 0; i < count2; i++) { - status = acpi_ns_check_object_type(data, this_element, - type2, - (i + count1 + start_index)); - if (ACPI_FAILURE(status)) { - return (status); - } - this_element++; - } - - return (AE_OK); -} - -/******************************************************************************* - * * FUNCTION: acpi_ns_check_object_type * * PARAMETERS: data - Pointer to validation data structure @@ -983,7 +403,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * ******************************************************************************/ -static acpi_status +acpi_status acpi_ns_check_object_type(struct acpi_predefined_data *data, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index) diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c new file mode 100644 index 000000000000..a40155467d2e --- /dev/null +++ b/drivers/acpi/acpica/nsprepkg.c @@ -0,0 +1,621 @@ +/****************************************************************************** + * + * Module Name: nsprepkg - Validation of package objects for predefined names + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsprepkg") + +/* Local prototypes */ +static acpi_status +acpi_ns_check_package_list(struct acpi_predefined_data *data, + const union acpi_predefined_info *package, + union acpi_operand_object **elements, u32 count); + +static acpi_status +acpi_ns_check_package_elements(struct acpi_predefined_data *data, + union acpi_operand_object **elements, + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index); + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package + * + * PARAMETERS: data - Pointer to validation data structure + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + ******************************************************************************/ + +acpi_status +acpi_ns_check_package(struct acpi_predefined_data *data, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + const union acpi_predefined_info *package; + union acpi_operand_object **elements; + acpi_status status = AE_OK; + u32 expected_count; + u32 count; + u32 i; + + ACPI_FUNCTION_NAME(ns_check_package); + + /* The package info for this name is in the next table entry */ + + package = data->predefined + 1; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + data->pathname, package->ret_info.type, + return_object->package.count)); + + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + acpi_ns_remove_null_elements(data, package->ret_info.type, + return_object); + + /* Extract package count and elements array */ + + elements = return_object->package.elements; + count = return_object->package.count; + + /* The package must have at least one element, else invalid */ + + if (!count) { + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Return Package has no elements (empty)")); + + return (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain sub-packages + */ + switch (package->ret_info.type) { + case ACPI_PTYPE1_FIXED: + + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (count < expected_count) { + goto package_too_small; + } else if (count > expected_count) { + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + data->pathname, count, + expected_count)); + } + + /* Validate all elements of the returned package */ + + status = acpi_ns_check_package_elements(data, elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2, 0); + break; + + case ACPI_PTYPE1_VAR: + + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < count; i++) { + status = acpi_ns_check_object_type(data, elements, + package->ret_info. + object_type1, i); + if (ACPI_FAILURE(status)) { + return (status); + } + elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + expected_count = package->ret_info3.count; + if (count < expected_count) { + goto package_too_small; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < count; i++) { + if (i < package->ret_info3.count) { + + /* These are the required package elements (0, 1, or 2) */ + + status = + acpi_ns_check_object_type(data, elements, + package-> + ret_info3. + object_type[i], + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* These are the optional package elements */ + + status = + acpi_ns_check_object_type(data, elements, + package-> + ret_info3. + tail_object_type, + i); + if (ACPI_FAILURE(status)) { + return (status); + } + } + elements++; + } + break; + + case ACPI_PTYPE2_REV_FIXED: + + /* First element is the (Integer) revision */ + + status = acpi_ns_check_object_type(data, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + elements++; + count--; + + /* Examine the sub-packages */ + + status = + acpi_ns_check_package_list(data, package, elements, count); + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + status = acpi_ns_check_object_type(data, elements, + ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + expected_count = (u32)(*elements)->integer.value; + if (expected_count >= count) { + goto package_too_small; + } + + count = expected_count; + elements++; + + /* Examine the sub-packages */ + + status = + acpi_ns_check_package_list(data, package, elements, count); + break; + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_FIX_VAR: + + /* + * These types all return a single Package that consists of a + * variable number of sub-Packages. + * + * First, ensure that the first element is a sub-Package. If not, + * the BIOS may have incorrectly returned the object as a single + * package instead of a Package of Packages (a common error if + * there is only one entry). We may be able to repair this by + * wrapping the returned Package with a new outer Package. + */ + if (*elements + && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { + + /* Create the new outer package and populate it */ + + status = + acpi_ns_wrap_with_package(data, return_object, + return_object_ptr); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Update locals to point to the new package (of 1 element) */ + + return_object = *return_object_ptr; + elements = return_object->package.elements; + count = 1; + } + + /* Examine the sub-packages */ + + status = + acpi_ns_check_package_list(data, package, elements, count); + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Invalid internal return type in table entry: %X", + package->ret_info.type)); + + return (AE_AML_INTERNAL); + } + + return (status); + + package_too_small: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Return Package is too small - found %u elements, expected %u", + count, expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_list + * + * PARAMETERS: data - Pointer to validation data structure + * package - Pointer to package-specific info for method + * elements - Element list of parent package. All elements + * of this list should be of type Package. + * count - Count of subpackages + * + * RETURN: Status + * + * DESCRIPTION: Examine a list of subpackages + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_list(struct acpi_predefined_data *data, + const union acpi_predefined_info *package, + union acpi_operand_object **elements, u32 count) +{ + union acpi_operand_object *sub_package; + union acpi_operand_object **sub_elements; + acpi_status status; + u32 expected_count; + u32 i; + u32 j; + + /* + * Validate each sub-Package in the parent Package + * + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to acpi_ns_remove_null_elements. + */ + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; + data->parent_package = sub_package; + + /* Each sub-object must be of type Package */ + + status = acpi_ns_check_object_type(data, &sub_package, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Examine the different types of expected sub-packages */ + + data->parent_package = sub_package; + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_REV_FIXED: + + /* Each subpackage has a fixed number of elements */ + + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(data, sub_elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + package->ret_info. + count2, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIX_VAR: + /* + * Each subpackage has a fixed number of elements and an + * optional element + */ + expected_count = + package->ret_info.count1 + package->ret_info.count2; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + status = + acpi_ns_check_package_elements(data, sub_elements, + package->ret_info. + object_type1, + package->ret_info. + count1, + package->ret_info. + object_type2, + sub_package->package. + count - + package->ret_info. + count1, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(data, + &sub_elements[j], + package-> + ret_info2. + object_type[j], + j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(data, sub_elements, + package->ret_info. + object_type1, + sub_package->package. + count, 0, 0, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + case ACPI_PTYPE2_COUNT: + + /* + * First element is the (Integer) count of elements, including + * the count field (the ACPI name is num_elements) + */ + status = acpi_ns_check_object_type(data, sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * Make sure package is large enough for the Count and is + * is as large as the minimum size + */ + expected_count = (u32)(*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + goto package_too_small; + } + if (sub_package->package.count < + package->ret_info.count1) { + expected_count = package->ret_info.count1; + goto package_too_small; + } + if (expected_count == 0) { + /* + * Either the num_entries element was originally zero or it was + * a NULL element and repaired to an Integer of value zero. + * In either case, repair it by setting num_entries to be the + * actual size of the subpackage. + */ + expected_count = sub_package->package.count; + (*sub_elements)->integer.value = expected_count; + } + + /* Check the type of each sub-package element */ + + status = + acpi_ns_check_package_elements(data, + (sub_elements + 1), + package->ret_info. + object_type1, + (expected_count - 1), + 0, 0, 1); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + + default: /* Should not get here, type was validated by caller */ + + return (AE_AML_INTERNAL); + } + + elements++; + } + + return (AE_OK); + + package_too_small: + + /* The sub-package count was smaller than required */ + + ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + "Return Sub-Package[%u] is too small - found %u elements, expected %u", + i, sub_package->package.count, expected_count)); + + return (AE_AML_OPERAND_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_package_elements + * + * PARAMETERS: data - Pointer to validation data structure + * elements - Pointer to the package elements array + * type1 - Object type for first group + * count1 - Count for first group + * type2 - Object type for second group + * count2 - Count for second group + * start_index - Start of the first group of elements + * + * RETURN: Status + * + * DESCRIPTION: Check that all elements of a package are of the correct object + * type. Supports up to two groups of different object types. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_check_package_elements(struct acpi_predefined_data *data, + union acpi_operand_object **elements, + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index) +{ + union acpi_operand_object **this_element = elements; + acpi_status status; + u32 i; + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + */ + for (i = 0; i < count1; i++) { + status = acpi_ns_check_object_type(data, this_element, + type1, i + start_index); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + for (i = 0; i < count2; i++) { + status = acpi_ns_check_object_type(data, this_element, + type2, + (i + count1 + start_index)); + if (ACPI_FAILURE(status)) { + return (status); + } + this_element++; + } + + return (AE_OK); +} diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 8c5f292860fc..9e833353c06a 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 90189251cdf0..ba4d98287c6a 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +55,8 @@ ACPI_MODULE_NAME("nsrepair2") */ typedef acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); + union acpi_operand_object + **return_object_ptr); typedef struct acpi_repair_info { char name[ACPI_NAME_SIZE]; diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 456cc859f869..5d43efc53a61 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -314,22 +314,7 @@ acpi_ns_search_and_enter(u32 target_name, * this problem, and we want to be able to enable ACPI support for them, * even though there are a few bad names. */ - if (!acpi_ut_valid_acpi_name(target_name)) { - target_name = - acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); - - /* Report warning only if in strict mode or debug mode */ - - if (!acpi_gbl_enable_interpreter_slack) { - ACPI_WARNING((AE_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - ACPI_CAST_PTR(char, &target_name))); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found bad character(s) in name, repaired: [%4.4s]\n", - ACPI_CAST_PTR(char, &target_name))); - } - } + acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name)); /* Try to find the name in the namespace level specified by the caller */ @@ -343,6 +328,11 @@ acpi_ns_search_and_enter(u32 target_name, if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) { status = AE_ALREADY_EXISTS; } +#ifdef ACPI_ASL_COMPILER + if (*return_node && (*return_node)->type == ACPI_TYPE_ANY) { + (*return_node)->flags |= ANOBJ_IS_EXTERNAL; + } +#endif /* Either found it or there was an error: finished either way */ diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index ef753a41e087..686420df684f 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,14 +46,11 @@ #include "accommon.h" #include "acnamesp.h" #include "amlcode.h" -#include "actables.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsutils") /* Local prototypes */ -static u8 acpi_ns_valid_path_separator(char sep); - #ifdef ACPI_OBSOLETE_FUNCTIONS acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); #endif @@ -99,42 +96,6 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node, /******************************************************************************* * - * FUNCTION: acpi_ns_valid_root_prefix - * - * PARAMETERS: prefix - Character to be checked - * - * RETURN: TRUE if a valid prefix - * - * DESCRIPTION: Check if a character is a valid ACPI Root prefix - * - ******************************************************************************/ - -u8 acpi_ns_valid_root_prefix(char prefix) -{ - - return ((u8) (prefix == '\\')); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_valid_path_separator - * - * PARAMETERS: sep - Character to be checked - * - * RETURN: TRUE if a valid path separator - * - * DESCRIPTION: Check if a character is a valid ACPI path separator - * - ******************************************************************************/ - -static u8 acpi_ns_valid_path_separator(char sep) -{ - - return ((u8) (sep == '.')); -} - -/******************************************************************************* - * * FUNCTION: acpi_ns_get_type * * PARAMETERS: node - Parent Node to be examined @@ -151,10 +112,10 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) if (!node) { ACPI_WARNING((AE_INFO, "Null Node parameter")); - return_UINT32(ACPI_TYPE_ANY); + return_VALUE(ACPI_TYPE_ANY); } - return_UINT32((acpi_object_type) node->type); + return_VALUE(node->type); } /******************************************************************************* @@ -179,10 +140,10 @@ u32 acpi_ns_local(acpi_object_type type) /* Type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); - return_UINT32(ACPI_NS_NORMAL); + return_VALUE(ACPI_NS_NORMAL); } - return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); + return_VALUE(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); } /******************************************************************************* @@ -218,19 +179,19 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) * * strlen() + 1 covers the first name_seg, which has no path separator */ - if (acpi_ns_valid_root_prefix(*next_external_char)) { + if (ACPI_IS_ROOT_PREFIX(*next_external_char)) { info->fully_qualified = TRUE; next_external_char++; /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ - while (acpi_ns_valid_root_prefix(*next_external_char)) { + while (ACPI_IS_ROOT_PREFIX(*next_external_char)) { next_external_char++; } } else { /* Handle Carat prefixes */ - while (*next_external_char == '^') { + while (ACPI_IS_PARENT_PREFIX(*next_external_char)) { info->num_carats++; next_external_char++; } @@ -244,7 +205,7 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) if (*next_external_char) { info->num_segments = 1; for (i = 0; next_external_char[i]; i++) { - if (acpi_ns_valid_path_separator(next_external_char[i])) { + if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) { info->num_segments++; } } @@ -282,7 +243,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) /* Setup the correct prefixes, counts, and pointers */ if (info->fully_qualified) { - internal_name[0] = '\\'; + internal_name[0] = AML_ROOT_PREFIX; if (num_segments <= 1) { result = &internal_name[1]; @@ -302,7 +263,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) i = 0; if (info->num_carats) { for (i = 0; i < info->num_carats; i++) { - internal_name[i] = '^'; + internal_name[i] = AML_PARENT_PREFIX; } } @@ -322,7 +283,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) for (; num_segments; num_segments--) { for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (acpi_ns_valid_path_separator(*external_name) || + if (ACPI_IS_PATH_SEPARATOR(*external_name) || (*external_name == 0)) { /* Pad the segment with underscore(s) if segment is short */ @@ -339,7 +300,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) /* Now we must have a path separator, or the pathname is bad */ - if (!acpi_ns_valid_path_separator(*external_name) && + if (!ACPI_IS_PATH_SEPARATOR(*external_name) && (*external_name != 0)) { return_ACPI_STATUS(AE_BAD_PATHNAME); } @@ -457,13 +418,13 @@ acpi_ns_externalize_name(u32 internal_name_length, /* Check for a prefix (one '\' | one or more '^') */ switch (internal_name[0]) { - case '\\': + case AML_ROOT_PREFIX: prefix_length = 1; break; - case '^': + case AML_PARENT_PREFIX: for (i = 0; i < internal_name_length; i++) { - if (internal_name[i] == '^') { + if (ACPI_IS_PARENT_PREFIX(internal_name[i])) { prefix_length = i + 1; } else { break; @@ -530,7 +491,7 @@ acpi_ns_externalize_name(u32 internal_name_length, ((num_segments > 0) ? (num_segments - 1) : 0) + 1; /* - * Check to see if we're still in bounds. If not, there's a problem + * Check to see if we're still in bounds. If not, there's a problem * with internal_name (invalid format). */ if (required_length > internal_name_length) { @@ -557,10 +518,14 @@ acpi_ns_externalize_name(u32 internal_name_length, (*converted_name)[j++] = '.'; } - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; - (*converted_name)[j++] = internal_name[names_index++]; + /* Copy and validate the 4-char name segment */ + + ACPI_MOVE_NAME(&(*converted_name)[j], + &internal_name[names_index]); + acpi_ut_repair_name(&(*converted_name)[j]); + + j += ACPI_NAME_SIZE; + names_index += ACPI_NAME_SIZE; } } @@ -660,17 +625,17 @@ void acpi_ns_terminate(void) u32 acpi_ns_opens_scope(acpi_object_type type) { - ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); + ACPI_FUNCTION_ENTRY(); - if (!acpi_ut_valid_object_type(type)) { + if (type > ACPI_TYPE_LOCAL_MAX) { /* type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); - return_UINT32(ACPI_NS_NORMAL); + return (ACPI_NS_NORMAL); } - return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); + return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); } /******************************************************************************* @@ -681,7 +646,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type) * \ (backslash) and ^ (carat) prefixes, and the * . (period) to separate segments are supported. * prefix_node - Root of subtree to be searched, or NS_ALL for the - * root of the name space. If Name is fully + * root of the name space. If Name is fully * qualified (first s8 is '\'), the passed value * of Scope will not be accessed. * flags - Used to indicate whether to perform upsearch or @@ -689,7 +654,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type) * return_node - Where the Node is returned * * DESCRIPTION: Look up a name relative to a given scope and return the - * corresponding Node. NOTE: Scope can be null. + * corresponding Node. NOTE: Scope can be null. * * MUTEX: Locks namespace * @@ -706,6 +671,8 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); + /* Simplest case is a null pathname */ + if (!pathname) { *return_node = prefix_node; if (!prefix_node) { @@ -714,6 +681,13 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, return_ACPI_STATUS(AE_OK); } + /* Quick check for a reference to the root */ + + if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) { + *return_node = acpi_gbl_root_node; + return_ACPI_STATUS(AE_OK); + } + /* Convert path to internal representation */ status = acpi_ns_internalize_name(pathname, &internal_path); diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 730bccc5e7f7..e70911a9e441 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,8 +60,8 @@ ACPI_MODULE_NAME("nswalk") * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if * none is found. * - * DESCRIPTION: Return the next peer node within the namespace. If Handle - * is valid, Scope is ignored. Otherwise, the first node + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node * within Scope is returned. * ******************************************************************************/ @@ -76,12 +76,12 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node /* It's really the parent's _scope_ that we want */ - return parent_node->child; + return (parent_node->child); } /* Otherwise just return the next peer */ - return child_node->peer; + return (child_node->peer); } /******************************************************************************* @@ -97,8 +97,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if * none is found. * - * DESCRIPTION: Return the next peer node within the namespace. If Handle - * is valid, Scope is ignored. Otherwise, the first node + * DESCRIPTION: Return the next peer node within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first node * within Scope is returned. * ******************************************************************************/ @@ -305,7 +305,7 @@ acpi_ns_walk_namespace(acpi_object_type type, /* * Depth first search: Attempt to go down another level in the - * namespace if we are allowed to. Don't go any further if we have + * namespace if we are allowed to. Don't go any further if we have * reached the caller specified maximum depth or if the user * function has specified that the maximum depth has been reached. */ diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 9692e6702333..fc69949151bb 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,16 +61,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); * PARAMETERS: handle - Object handle (optional) * pathname - Object pathname (optional) * external_params - List of parameters to pass to method, - * terminated by NULL. May be NULL + * terminated by NULL. May be NULL * if no parameters are being passed. * return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. + * any). If NULL, no value is returned. * return_type - Expected type of return object * * RETURN: Status * * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must + * parameters if necessary. One of "Handle" or "Pathname" must * be valid (non-null) * ******************************************************************************/ @@ -155,15 +155,15 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) * PARAMETERS: handle - Object handle (optional) * pathname - Object pathname (optional) * external_params - List of parameters to pass to method, - * terminated by NULL. May be NULL + * terminated by NULL. May be NULL * if no parameters are being passed. * return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. + * any). If NULL, no value is returned. * * RETURN: Status * * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must + * parameters if necessary. One of "Handle" or "Pathname" must * be valid (non-null) * ******************************************************************************/ @@ -236,7 +236,7 @@ acpi_evaluate_object(acpi_handle handle, * 2) No handle, not fully qualified pathname (error) * 3) Valid handle */ - if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { + if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { /* The path is fully qualified, just evaluate by name */ @@ -492,7 +492,7 @@ acpi_walk_namespace(acpi_object_type type, */ status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock); if (ACPI_FAILURE(status)) { - return status; + return_ACPI_STATUS(status); } /* @@ -542,8 +542,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, acpi_status status; struct acpi_namespace_node *node; u32 flags; - struct acpica_device_id *hid; - struct acpica_device_id_list *cid; + struct acpi_pnp_device_id *hid; + struct acpi_pnp_device_id_list *cid; u32 i; u8 found; int no_match; @@ -602,17 +602,22 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* Walk the CID list */ - found = 0; + found = FALSE; for (i = 0; i < cid->count; i++) { if (ACPI_STRCMP(cid->ids[i].string, info->hid) == 0) { - found = 1; + + /* Found a matching CID */ + + found = TRUE; break; } } + ACPI_FREE(cid); - if (!found) + if (!found) { return (AE_OK); + } } } @@ -656,7 +661,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, * starting (and ending) at the object specified by start_handle. * The user_function is called whenever an object of type - * Device is found. If the user function returns + * Device is found. If the user function returns * a non-zero value, the search is terminated immediately and this * value is returned to the caller. * diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 08e9610b34ca..f3a4d95899f7 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,8 +53,8 @@ ACPI_MODULE_NAME("nsxfname") /* Local prototypes */ -static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, - struct acpica_device_id *source, +static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, + struct acpi_pnp_device_id *source, char *string_area); /****************************************************************************** @@ -69,8 +69,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, * RETURN: Status * * DESCRIPTION: This routine will search for a caller specified name in the - * name space. The caller can restrict the search region by - * specifying a non NULL parent. The parent value is itself a + * name space. The caller can restrict the search region by + * specifying a non NULL parent. The parent value is itself a * namespace handle. * ******************************************************************************/ @@ -107,7 +107,7 @@ acpi_get_handle(acpi_handle parent, * * Error for <null Parent + relative path> */ - if (acpi_ns_valid_root_prefix(pathname[0])) { + if (ACPI_IS_ROOT_PREFIX(pathname[0])) { /* Pathname is fully qualified (starts with '\') */ @@ -149,7 +149,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_handle) * RETURN: Pointer to a string containing the fully qualified Name. * * DESCRIPTION: This routine returns the fully qualified name associated with - * the Handle parameter. This and the acpi_pathname_to_handle are + * the Handle parameter. This and the acpi_pathname_to_handle are * complementary functions. * ******************************************************************************/ @@ -202,8 +202,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) /* Just copy the ACPI name from the Node and zero terminate it */ - ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node), - ACPI_NAME_SIZE); + ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node)); ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; status = AE_OK; @@ -219,20 +218,21 @@ ACPI_EXPORT_SYMBOL(acpi_get_name) * * FUNCTION: acpi_ns_copy_device_id * - * PARAMETERS: dest - Pointer to the destination DEVICE_ID - * source - Pointer to the source DEVICE_ID + * PARAMETERS: dest - Pointer to the destination PNP_DEVICE_ID + * source - Pointer to the source PNP_DEVICE_ID * string_area - Pointer to where to copy the dest string * * RETURN: Pointer to the next string area * - * DESCRIPTION: Copy a single DEVICE_ID, including the string data. + * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data. * ******************************************************************************/ -static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, - struct acpica_device_id *source, +static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, + struct acpi_pnp_device_id *source, char *string_area) { - /* Create the destination DEVICE_ID */ + + /* Create the destination PNP_DEVICE_ID */ dest->string = string_area; dest->length = source->length; @@ -256,8 +256,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, * namespace node and possibly by running several standard * control methods (Such as in the case of a device.) * - * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, - * _ADR, _sx_w, and _sx_d methods. + * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB, + * _STA, _ADR, _sx_w, and _sx_d methods. * * Note: Allocates the return buffer, must be freed by the caller. * @@ -269,9 +269,10 @@ acpi_get_object_info(acpi_handle handle, { struct acpi_namespace_node *node; struct acpi_device_info *info; - struct acpica_device_id_list *cid_list = NULL; - struct acpica_device_id *hid = NULL; - struct acpica_device_id *uid = NULL; + struct acpi_pnp_device_id_list *cid_list = NULL; + struct acpi_pnp_device_id *hid = NULL; + struct acpi_pnp_device_id *uid = NULL; + struct acpi_pnp_device_id *sub = NULL; char *next_id_string; acpi_object_type type; acpi_name name; @@ -289,7 +290,7 @@ acpi_get_object_info(acpi_handle handle, status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - goto cleanup; + return (status); } node = acpi_ns_validate_handle(handle); @@ -316,7 +317,7 @@ acpi_get_object_info(acpi_handle handle, if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { /* * Get extra info for ACPI Device/Processor objects only: - * Run the Device _HID, _UID, and _CID methods. + * Run the Device _HID, _UID, _SUB, and _CID methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used @@ -339,6 +340,14 @@ acpi_get_object_info(acpi_handle handle, valid |= ACPI_VALID_UID; } + /* Execute the Device._SUB method */ + + status = acpi_ut_execute_SUB(node, &sub); + if (ACPI_SUCCESS(status)) { + info_size += sub->length; + valid |= ACPI_VALID_SUB; + } + /* Execute the Device._CID method */ status = acpi_ut_execute_CID(node, &cid_list); @@ -348,7 +357,7 @@ acpi_get_object_info(acpi_handle handle, info_size += (cid_list->list_size - - sizeof(struct acpica_device_id_list)); + sizeof(struct acpi_pnp_device_id_list)); valid |= ACPI_VALID_CID; } } @@ -418,16 +427,17 @@ acpi_get_object_info(acpi_handle handle, next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); if (cid_list) { - /* Point past the CID DEVICE_ID array */ + /* Point past the CID PNP_DEVICE_ID array */ next_id_string += ((acpi_size) cid_list->count * - sizeof(struct acpica_device_id)); + sizeof(struct acpi_pnp_device_id)); } /* - * Copy the HID, UID, and CIDs to the return buffer. The variable-length - * strings are copied to the reserved area at the end of the buffer. + * Copy the HID, UID, SUB, and CIDs to the return buffer. + * The variable-length strings are copied to the reserved area + * at the end of the buffer. * * For HID and CID, check if the ID is a PCI Root Bridge. */ @@ -445,6 +455,11 @@ acpi_get_object_info(acpi_handle handle, uid, next_id_string); } + if (sub) { + next_id_string = acpi_ns_copy_device_id(&info->subsystem_id, + sub, next_id_string); + } + if (cid_list) { info->compatible_id_list.count = cid_list->count; info->compatible_id_list.list_size = cid_list->list_size; @@ -481,6 +496,9 @@ acpi_get_object_info(acpi_handle handle, if (uid) { ACPI_FREE(uid); } + if (sub) { + ACPI_FREE(sub); + } if (cid_list) { ACPI_FREE(cid_list); } @@ -521,14 +539,14 @@ acpi_status acpi_install_method(u8 *buffer) /* Parameter validation */ if (!buffer) { - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } /* Table must be a DSDT or SSDT */ if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) && !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { - return AE_BAD_HEADER; + return (AE_BAD_HEADER); } /* First AML opcode in the table must be a control method */ @@ -536,7 +554,7 @@ acpi_status acpi_install_method(u8 *buffer) parser_state.aml = buffer + sizeof(struct acpi_table_header); opcode = acpi_ps_peek_opcode(&parser_state); if (opcode != AML_METHOD_OP) { - return AE_BAD_PARAMETER; + return (AE_BAD_PARAMETER); } /* Extract method information from the raw AML */ @@ -554,13 +572,13 @@ acpi_status acpi_install_method(u8 *buffer) */ aml_buffer = ACPI_ALLOCATE(aml_length); if (!aml_buffer) { - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); if (!method_obj) { ACPI_FREE(aml_buffer); - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } /* Lock namespace for acpi_ns_lookup, we may be creating a new node */ @@ -626,12 +644,12 @@ acpi_status acpi_install_method(u8 *buffer) /* Remove local reference to the method object */ acpi_ut_remove_reference(method_obj); - return status; + return (status); error_exit: ACPI_FREE(aml_buffer); ACPI_FREE(method_obj); - return status; + return (status); } ACPI_EXPORT_SYMBOL(acpi_install_method) diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 6766fc4f088f..c0853ef294e4 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -220,8 +220,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_parent) * * RETURN: Status * - * DESCRIPTION: Return the next peer object within the namespace. If Handle is - * valid, Scope is ignored. Otherwise, the first object within + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within * Scope is returned. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 844464c4f901..f51308cdbc65 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +108,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ package_length |= (aml[0] & byte_zero_mask); - return_UINT32(package_length); + return_VALUE(package_length); } /******************************************************************************* @@ -120,7 +120,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state) * RETURN: Pointer to end-of-package +1 * * DESCRIPTION: Get next package length and return a pointer past the end of - * the package. Consumes the package length field + * the package. Consumes the package length field * ******************************************************************************/ @@ -147,8 +147,8 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state) * RETURN: Pointer to the start of the name string (pointer points into * the AML. * - * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name - * prefix characters. Set parser state to point past the string. + * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name + * prefix characters. Set parser state to point past the string. * (Name is consumed from the AML.) * ******************************************************************************/ @@ -162,7 +162,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) /* Point past any namestring prefix characters (backslash or carat) */ - while (acpi_ps_is_prefix_char(*end)) { + while (ACPI_IS_ROOT_PREFIX(*end) || ACPI_IS_PARENT_PREFIX(*end)) { end++; } @@ -220,7 +220,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state) * * DESCRIPTION: Get next name (if method call, return # of required args). * Names are looked up in the internal namespace to determine - * if the name represents a control method. If a method + * if the name represents a control method. If a method * is found, the number of arguments to the method is returned. * This information is critical for parsing to continue correctly. * @@ -798,7 +798,8 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, subop = acpi_ps_peek_opcode(parser_state); if (subop == 0 || acpi_ps_is_leading_char(subop) || - acpi_ps_is_prefix_char(subop)) { + ACPI_IS_ROOT_PREFIX(subop) || + ACPI_IS_PARENT_PREFIX(subop)) { /* null_name or name_string */ diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 799162c1b6df..63c455447481 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,324 +58,17 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psloop") -static u32 acpi_gbl_depth = 0; - /* Local prototypes */ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op); - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op); - static acpi_status acpi_ps_get_arguments(struct acpi_walk_state *walk_state, u8 * aml_op_start, union acpi_parse_object *op); -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status); - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status); - static void acpi_ps_link_module_code(union acpi_parse_object *parent_op, u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); /******************************************************************************* * - * FUNCTION: acpi_ps_get_aml_opcode - * - * PARAMETERS: walk_state - Current state - * - * RETURN: Status - * - * DESCRIPTION: Extract the next AML opcode from the input stream. - * - ******************************************************************************/ - -static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); - - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state.aml_start); - walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); - - /* - * First cut to determine what we have found: - * 1) A valid AML opcode - * 2) A name string - * 3) An unknown/invalid opcode - */ - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - - switch (walk_state->op_info->class) { - case AML_CLASS_ASCII: - case AML_CLASS_PREFIX: - /* - * Starts with a valid prefix or ASCII char, this is a name - * string. Convert the bare name string to a namepath. - */ - walk_state->opcode = AML_INT_NAMEPATH_OP; - walk_state->arg_types = ARGP_NAMESTRING; - break; - - case AML_CLASS_UNKNOWN: - - /* The opcode is unrecognized. Just skip unknown opcodes */ - - ACPI_ERROR((AE_INFO, - "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring", - walk_state->opcode, walk_state->parser_state.aml, - walk_state->aml_offset)); - - ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128); - - /* Assume one-byte bad opcode */ - - walk_state->parser_state.aml++; - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - - default: - - /* Found opcode info, this is a normal opcode */ - - walk_state->parser_state.aml += - acpi_ps_get_opcode_size(walk_state->opcode); - walk_state->arg_types = walk_state->op_info->parse_args; - break; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_build_named_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Begin of named Op in AML - * unnamed_op - Early Op (not a named Op) - * op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Parse a named Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_build_named_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, - union acpi_parse_object *unnamed_op, - union acpi_parse_object **op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *arg = NULL; - - ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); - - unnamed_op->common.value.arg = NULL; - unnamed_op->common.arg_list_length = 0; - unnamed_op->common.aml_opcode = walk_state->opcode; - - /* - * Get and append arguments until we find the node that contains - * the name (the type ARGP_NAME). - */ - while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && - (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { - status = - acpi_ps_get_next_arg(walk_state, - &(walk_state->parser_state), - GET_CURRENT_ARG_TYPE(walk_state-> - arg_types), &arg); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(unnamed_op, arg); - INCREMENT_ARG_LIST(walk_state->arg_types); - } - - /* - * Make sure that we found a NAME and didn't run out of arguments - */ - if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - - /* We know that this arg is a name, move to next arg */ - - INCREMENT_ARG_LIST(walk_state->arg_types); - - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = NULL; - - status = walk_state->descending_callback(walk_state, op); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); - return_ACPI_STATUS(status); - } - - if (!*op) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - status = acpi_ps_next_parse_state(walk_state, *op, status); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_PENDING) { - return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); - } - return_ACPI_STATUS(status); - } - - acpi_ps_append_arg(*op, unnamed_op->common.value.arg); - acpi_gbl_depth++; - - if ((*op)->common.aml_opcode == AML_REGION_OP || - (*op)->common.aml_opcode == AML_DATA_REGION_OP) { - /* - * Defer final parsing of an operation_region body, because we don't - * have enough info in the first pass to parse it correctly (i.e., - * there may be method calls within the term_arg elements of the body.) - * - * However, we must continue parsing because the opregion is not a - * standalone package -- we don't know where the end is at this point. - * - * (Length is unknown until parse of the body complete) - */ - (*op)->named.data = aml_op_start; - (*op)->named.length = 0; - } - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_create_op - * - * PARAMETERS: walk_state - Current state - * aml_op_start - Op start in AML - * new_op - Returned Op - * - * RETURN: Status - * - * DESCRIPTION: Get Op from AML - * - ******************************************************************************/ - -static acpi_status -acpi_ps_create_op(struct acpi_walk_state *walk_state, - u8 * aml_op_start, union acpi_parse_object **new_op) -{ - acpi_status status = AE_OK; - union acpi_parse_object *op; - union acpi_parse_object *named_op = NULL; - union acpi_parse_object *parent_scope; - u8 argument_count; - const struct acpi_opcode_info *op_info; - - ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); - - status = acpi_ps_get_aml_opcode(walk_state); - if (status == AE_CTRL_PARSE_CONTINUE) { - return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); - } - - /* Create Op structure and append to parent's argument list */ - - walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - op = acpi_ps_alloc_op(walk_state->opcode); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - if (walk_state->op_info->flags & AML_NAMED) { - status = - acpi_ps_build_named_op(walk_state, aml_op_start, op, - &named_op); - acpi_ps_free_op(op); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - *new_op = named_op; - return_ACPI_STATUS(AE_OK); - } - - /* Not a named opcode, just allocate Op and append to parent */ - - if (walk_state->op_info->flags & AML_CREATE) { - /* - * Backup to beginning of create_XXXfield declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - if (walk_state->opcode == AML_BANK_FIELD_OP) { - /* - * Backup to beginning of bank_field declaration - * body_length is unknown until we parse the body - */ - op->named.data = aml_op_start; - op->named.length = 0; - } - - parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); - acpi_ps_append_arg(parent_scope, op); - - if (parent_scope) { - op_info = - acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); - if (op_info->flags & AML_HAS_TARGET) { - argument_count = - acpi_ps_get_argument_count(op_info->type); - if (parent_scope->common.arg_list_length > - argument_count) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { - op->common.flags |= ACPI_PARSEOP_TARGET; - } - } - - if (walk_state->descending_callback != NULL) { - /* - * Find the object. This will either insert the object into - * the namespace or simply look it up - */ - walk_state->op = *new_op = op; - - status = walk_state->descending_callback(walk_state, &op); - status = acpi_ps_next_parse_state(walk_state, op, status); - if (status == AE_CTRL_PENDING) { - status = AE_CTRL_PARSE_PENDING; - } - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ps_get_arguments * * PARAMETERS: walk_state - Current state @@ -519,11 +212,18 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, if ((op_info->class == AML_CLASS_EXECUTE) && (!arg)) { ACPI_WARNING((AE_INFO, - "Detected an unsupported executable opcode " - "at module-level: [0x%.4X] at table offset 0x%.4X", - op->common.aml_opcode, - (u32)((aml_op_start - walk_state->parser_state.aml_start) - + sizeof(struct acpi_table_header)))); + "Unsupported module-level executable opcode " + "0x%.2X at table offset 0x%.4X", + op->common. + aml_opcode, + (u32) + (ACPI_PTR_DIFF + (aml_op_start, + walk_state-> + parser_state. + aml_start) + + sizeof(struct + acpi_table_header)))); } } break; @@ -676,290 +376,6 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, /******************************************************************************* * - * FUNCTION: acpi_ps_complete_op - * - * PARAMETERS: walk_state - Current state - * op - Returned Op - * status - Parse status before complete Op - * - * RETURN: Status - * - * DESCRIPTION: Complete Op - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_op(struct acpi_walk_state *walk_state, - union acpi_parse_object **op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); - - /* - * Finished one argument of the containing scope - */ - walk_state->parser_state.scope->parse_scope.arg_count--; - - /* Close this Op (will result in parse subtree deletion) */ - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - *op = NULL; - - switch (status) { - case AE_OK: - break; - - case AE_CTRL_TRANSFER: - - /* We are about to transfer to a called method */ - - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - - case AE_CTRL_END: - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - if (*op) { - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - status = AE_OK; - break; - - case AE_CTRL_BREAK: - case AE_CTRL_CONTINUE: - - /* Pop off scopes until we find the While */ - - while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - } - - /* Close this iteration of the While loop */ - - walk_state->op = *op; - walk_state->op_info = - acpi_ps_get_opcode_info((*op)->common.aml_opcode); - walk_state->opcode = (*op)->common.aml_opcode; - - status = walk_state->ascending_callback(walk_state); - status = acpi_ps_next_parse_state(walk_state, *op, status); - - status2 = acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - status = AE_OK; - break; - - case AE_CTRL_TERMINATE: - - /* Clean up */ - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - - acpi_ut_delete_generic_state - (acpi_ut_pop_generic_state - (&walk_state->control_state)); - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - - return_ACPI_STATUS(AE_OK); - - default: /* All other non-AE_OK status */ - - do { - if (*op) { - status2 = - acpi_ps_complete_this_op(walk_state, *op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (*op); - -#if 0 - /* - * TBD: Cleanup parse ops on error - */ - if (*op == NULL) { - acpi_ps_pop_scope(parser_state, op, - &walk_state->arg_types, - &walk_state->arg_count); - } -#endif - walk_state->prev_op = NULL; - walk_state->prev_arg_types = walk_state->arg_types; - return_ACPI_STATUS(status); - } - - /* This scope complete? */ - - if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { - acpi_ps_pop_scope(&(walk_state->parser_state), op, - &walk_state->arg_types, - &walk_state->arg_count); - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); - } else { - *op = NULL; - } - - ACPI_PREEMPTION_POINT(); - - return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_complete_final_op - * - * PARAMETERS: walk_state - Current state - * op - Current Op - * status - Current parse status before complete last - * Op - * - * RETURN: Status - * - * DESCRIPTION: Complete last Op. - * - ******************************************************************************/ - -static acpi_status -acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, - union acpi_parse_object *op, acpi_status status) -{ - acpi_status status2; - - ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); - - /* - * Complete the last Op (if not completed), and clear the scope stack. - * It is easily possible to end an AML "package" with an unbounded number - * of open scopes (such as when several ASL blocks are closed with - * sequential closing braces). We want to terminate each one cleanly. - */ - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", - op)); - do { - if (op) { - if (walk_state->ascending_callback != NULL) { - walk_state->op = op; - walk_state->op_info = - acpi_ps_get_opcode_info(op->common. - aml_opcode); - walk_state->opcode = op->common.aml_opcode; - - status = - walk_state->ascending_callback(walk_state); - status = - acpi_ps_next_parse_state(walk_state, op, - status); - if (status == AE_CTRL_PENDING) { - status = - acpi_ps_complete_op(walk_state, &op, - AE_OK); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - - if (status == AE_CTRL_TERMINATE) { - status = AE_OK; - - /* Clean up */ - do { - if (op) { - status2 = - acpi_ps_complete_this_op - (walk_state, op); - if (ACPI_FAILURE - (status2)) { - return_ACPI_STATUS - (status2); - } - } - - acpi_ps_pop_scope(& - (walk_state-> - parser_state), - &op, - &walk_state-> - arg_types, - &walk_state-> - arg_count); - - } while (op); - - return_ACPI_STATUS(status); - } - - else if (ACPI_FAILURE(status)) { - - /* First error is most important */ - - (void) - acpi_ps_complete_this_op(walk_state, - op); - return_ACPI_STATUS(status); - } - } - - status2 = acpi_ps_complete_this_op(walk_state, op); - if (ACPI_FAILURE(status2)) { - return_ACPI_STATUS(status2); - } - } - - acpi_ps_pop_scope(&(walk_state->parser_state), &op, - &walk_state->arg_types, - &walk_state->arg_count); - - } while (op); - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ps_parse_loop * * PARAMETERS: walk_state - Current state @@ -1144,10 +560,6 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { - if (acpi_gbl_depth) { - acpi_gbl_depth--; - } - if (op->common.aml_opcode == AML_REGION_OP || op->common.aml_opcode == AML_DATA_REGION_OP) { /* diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c new file mode 100644 index 000000000000..12c4028002b1 --- /dev/null +++ b/drivers/acpi/acpica/psobject.c @@ -0,0 +1,647 @@ +/****************************************************************************** + * + * Module Name: psobject - Support for parse objects + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psobject") + +/* Local prototypes */ +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_aml_opcode + * + * PARAMETERS: walk_state - Current state + * + * RETURN: Status + * + * DESCRIPTION: Extract the next AML opcode from the input stream. + * + ******************************************************************************/ + +static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); + + walk_state->aml_offset = + (u32)ACPI_PTR_DIFF(walk_state->parser_state.aml, + walk_state->parser_state.aml_start); + walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + + switch (walk_state->op_info->class) { + case AML_CLASS_ASCII: + case AML_CLASS_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + walk_state->opcode = AML_INT_NAMEPATH_OP; + walk_state->arg_types = ARGP_NAMESTRING; + break; + + case AML_CLASS_UNKNOWN: + + /* The opcode is unrecognized. Complain and skip unknown opcodes */ + + if (walk_state->pass_number == 2) { + ACPI_ERROR((AE_INFO, + "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", + walk_state->opcode, + (u32)(walk_state->aml_offset + + sizeof(struct acpi_table_header)))); + + ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16), + 48); + +#ifdef ACPI_ASL_COMPILER + /* + * This is executed for the disassembler only. Output goes + * to the disassembled ASL output file. + */ + acpi_os_printf + ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", + walk_state->opcode, + (u32)(walk_state->aml_offset + + sizeof(struct acpi_table_header))); + + /* Dump the context surrounding the invalid opcode */ + + acpi_ut_dump_buffer(((u8 *)walk_state->parser_state. + aml - 16), 48, DB_BYTE_DISPLAY, + (walk_state->aml_offset + + sizeof(struct acpi_table_header) - + 16)); + acpi_os_printf(" */\n"); +#endif + } + + /* Increment past one-byte or two-byte opcode */ + + walk_state->parser_state.aml++; + if (walk_state->opcode > 0xFF) { /* Can only happen if first byte is 0x5B */ + walk_state->parser_state.aml++; + } + + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + + default: + + /* Found opcode info, this is a normal opcode */ + + walk_state->parser_state.aml += + acpi_ps_get_opcode_size(walk_state->opcode); + walk_state->arg_types = walk_state->op_info->parse_args; + break; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_build_named_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Begin of named Op in AML + * unnamed_op - Early Op (not a named Op) + * op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Parse a named Op + * + ******************************************************************************/ + +acpi_status +acpi_ps_build_named_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, + union acpi_parse_object *unnamed_op, + union acpi_parse_object **op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *arg = NULL; + + ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); + + unnamed_op->common.value.arg = NULL; + unnamed_op->common.arg_list_length = 0; + unnamed_op->common.aml_opcode = walk_state->opcode; + + /* + * Get and append arguments until we find the node that contains + * the name (the type ARGP_NAME). + */ + while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && + (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { + status = + acpi_ps_get_next_arg(walk_state, + &(walk_state->parser_state), + GET_CURRENT_ARG_TYPE(walk_state-> + arg_types), &arg); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(unnamed_op, arg); + INCREMENT_ARG_LIST(walk_state->arg_types); + } + + /* + * Make sure that we found a NAME and didn't run out of arguments + */ + if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { + return_ACPI_STATUS(AE_AML_NO_OPERAND); + } + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST(walk_state->arg_types); + + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = NULL; + + status = walk_state->descending_callback(walk_state, op); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); + return_ACPI_STATUS(status); + } + + if (!*op) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + status = acpi_ps_next_parse_state(walk_state, *op, status); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_PENDING) { + return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); + } + return_ACPI_STATUS(status); + } + + acpi_ps_append_arg(*op, unnamed_op->common.value.arg); + + if ((*op)->common.aml_opcode == AML_REGION_OP || + (*op)->common.aml_opcode == AML_DATA_REGION_OP) { + /* + * Defer final parsing of an operation_region body, because we don't + * have enough info in the first pass to parse it correctly (i.e., + * there may be method calls within the term_arg elements of the body.) + * + * However, we must continue parsing because the opregion is not a + * standalone package -- we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + (*op)->named.data = aml_op_start; + (*op)->named.length = 0; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_create_op + * + * PARAMETERS: walk_state - Current state + * aml_op_start - Op start in AML + * new_op - Returned Op + * + * RETURN: Status + * + * DESCRIPTION: Get Op from AML + * + ******************************************************************************/ + +acpi_status +acpi_ps_create_op(struct acpi_walk_state *walk_state, + u8 *aml_op_start, union acpi_parse_object **new_op) +{ + acpi_status status = AE_OK; + union acpi_parse_object *op; + union acpi_parse_object *named_op = NULL; + union acpi_parse_object *parent_scope; + u8 argument_count; + const struct acpi_opcode_info *op_info; + + ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); + + status = acpi_ps_get_aml_opcode(walk_state); + if (status == AE_CTRL_PARSE_CONTINUE) { + return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); + } + + /* Create Op structure and append to parent's argument list */ + + walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode); + if (!op) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + if (walk_state->op_info->flags & AML_NAMED) { + status = + acpi_ps_build_named_op(walk_state, aml_op_start, op, + &named_op); + acpi_ps_free_op(op); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *new_op = named_op; + return_ACPI_STATUS(AE_OK); + } + + /* Not a named opcode, just allocate Op and append to parent */ + + if (walk_state->op_info->flags & AML_CREATE) { + /* + * Backup to beginning of create_XXXfield declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + if (walk_state->opcode == AML_BANK_FIELD_OP) { + /* + * Backup to beginning of bank_field declaration + * body_length is unknown until we parse the body + */ + op->named.data = aml_op_start; + op->named.length = 0; + } + + parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); + acpi_ps_append_arg(parent_scope, op); + + if (parent_scope) { + op_info = + acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); + if (op_info->flags & AML_HAS_TARGET) { + argument_count = + acpi_ps_get_argument_count(op_info->type); + if (parent_scope->common.arg_list_length > + argument_count) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { + op->common.flags |= ACPI_PARSEOP_TARGET; + } + } + + if (walk_state->descending_callback != NULL) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + walk_state->op = *new_op = op; + + status = walk_state->descending_callback(walk_state, &op); + status = acpi_ps_next_parse_state(walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_CTRL_PARSE_PENDING; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_op + * + * PARAMETERS: walk_state - Current state + * op - Returned Op + * status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); + + /* + * Finished one argument of the containing scope + */ + walk_state->parser_state.scope->parse_scope.arg_count--; + + /* Close this Op (will result in parse subtree deletion) */ + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + *op = NULL; + + switch (status) { + case AE_OK: + break; + + case AE_CTRL_TRANSFER: + + /* We are about to transfer to a called method */ + + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + + case AE_CTRL_END: + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + if (*op) { + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + status = AE_OK; + break; + + case AE_CTRL_BREAK: + case AE_CTRL_CONTINUE: + + /* Pop off scopes until we find the While */ + + while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + } + + /* Close this iteration of the While loop */ + + walk_state->op = *op; + walk_state->op_info = + acpi_ps_get_opcode_info((*op)->common.aml_opcode); + walk_state->opcode = (*op)->common.aml_opcode; + + status = walk_state->ascending_callback(walk_state); + status = acpi_ps_next_parse_state(walk_state, *op, status); + + status2 = acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + status = AE_OK; + break; + + case AE_CTRL_TERMINATE: + + /* Clean up */ + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + + return_ACPI_STATUS(AE_OK); + + default: /* All other non-AE_OK status */ + + do { + if (*op) { + status2 = + acpi_ps_complete_this_op(walk_state, *op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (*op); + +#if 0 + /* + * TBD: Cleanup parse ops on error + */ + if (*op == NULL) { + acpi_ps_pop_scope(parser_state, op, + &walk_state->arg_types, + &walk_state->arg_count); + } +#endif + walk_state->prev_op = NULL; + walk_state->prev_arg_types = walk_state->arg_types; + return_ACPI_STATUS(status); + } + + /* This scope complete? */ + + if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { + acpi_ps_pop_scope(&(walk_state->parser_state), op, + &walk_state->arg_types, + &walk_state->arg_count); + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); + } else { + *op = NULL; + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_complete_final_op + * + * PARAMETERS: walk_state - Current state + * op - Current Op + * status - Current parse status before complete last + * Op + * + * RETURN: Status + * + * DESCRIPTION: Complete last Op. + * + ******************************************************************************/ + +acpi_status +acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status) +{ + acpi_status status2; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several ASL blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", + op)); + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. + aml_opcode); + walk_state->opcode = op->common.aml_opcode; + + status = + walk_state->ascending_callback(walk_state); + status = + acpi_ps_next_parse_state(walk_state, op, + status); + if (status == AE_CTRL_PENDING) { + status = + acpi_ps_complete_op(walk_state, &op, + AE_OK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + status2 = + acpi_ps_complete_this_op + (walk_state, op); + if (ACPI_FAILURE + (status2)) { + return_ACPI_STATUS + (status2); + } + } + + acpi_ps_pop_scope(& + (walk_state-> + parser_state), + &op, + &walk_state-> + arg_types, + &walk_state-> + arg_count); + + } while (op); + + return_ACPI_STATUS(status); + } + + else if (ACPI_FAILURE(status)) { + + /* First error is most important */ + + (void) + acpi_ps_complete_this_op(walk_state, + op); + return_ACPI_STATUS(status); + } + } + + status2 = acpi_ps_complete_this_op(walk_state, op); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + } + + acpi_ps_pop_scope(&(walk_state->parser_state), &op, + &walk_state->arg_types, + &walk_state->arg_count); + + } while (op); + + return_ACPI_STATUS(status); +} diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index ed1d457bd5ca..1b659e59710a 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,27 +43,22 @@ #include <acpi/acpi.h> #include "accommon.h" -#include "acparser.h" #include "acopcode.h" #include "amlcode.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopcode") -static const u8 acpi_gbl_argument_count[] = - { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; - /******************************************************************************* * * NAME: acpi_gbl_aml_op_info * * DESCRIPTION: Opcode table. Each entry contains <opcode, type, name, operands> * The name is a simple ascii string, the operand specifier is an - * ascii string with one letter per operand. The letter specifies + * ascii string with one letter per operand. The letter specifies * the operand type. * ******************************************************************************/ - /* * Summary of opcode types/flags * @@ -181,9 +176,8 @@ static const u8 acpi_gbl_argument_count[] = AML_CREATE_QWORD_FIELD_OP ******************************************************************************/ - /* - * Master Opcode information table. A summary of everything we know about each + * Master Opcode information table. A summary of everything we know about each * opcode, all in one place. */ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { @@ -392,10 +386,12 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), @@ -495,7 +491,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { AML_NSNODE | AML_NAMED | AML_DEFER), /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, @@ -519,12 +516,13 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | - AML_DEFER), + ACPI_TYPE_LOCAL_BANK_FIELD, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD | AML_DEFER), /* Internal opcodes that map to invalid AML opcodes */ @@ -632,7 +630,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE), + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE), /* ACPI 3.0 opcodes */ @@ -651,169 +650,3 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /*! [End] no source code translation !*/ }; - -/* - * This table is directly indexed by the opcodes, and returns an - * index into the table above - */ -static const u8 acpi_gbl_short_op_index[256] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, -/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, -/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, -/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, -/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, -/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, -/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, -/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, -/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, -/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, -/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, -/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, -/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, -/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, -/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, -/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, -/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, -}; - -/* - * This table is indexed by the second opcode of the extended opcode - * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) - */ -static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { -/* 0 1 2 3 4 5 6 7 */ -/* 8 9 A B C D E F */ -/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, -/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, -/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, -/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, -/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, -/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, -/* 0x88 */ 0x7C, -}; - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_info - * - * PARAMETERS: opcode - The AML opcode - * - * RETURN: A pointer to the info about the opcode. - * - * DESCRIPTION: Find AML opcode description based on the opcode. - * NOTE: This procedure must ALWAYS return a valid pointer! - * - ******************************************************************************/ - -const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) -{ - ACPI_FUNCTION_NAME(ps_get_opcode_info); - - /* - * Detect normal 8-bit opcode or extended 16-bit opcode - */ - if (!(opcode & 0xFF00)) { - - /* Simple (8-bit) opcode: 0-255, can't index beyond table */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_short_op_index[(u8) opcode]]); - } - - if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && - (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { - - /* Valid extended (16-bit) opcode */ - - return (&acpi_gbl_aml_op_info - [acpi_gbl_long_op_index[(u8) opcode]]); - } - - /* Unknown AML opcode */ - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Unknown AML opcode [%4.4X]\n", opcode)); - - return (&acpi_gbl_aml_op_info[_UNK]); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_opcode_name - * - * PARAMETERS: opcode - The AML opcode - * - * RETURN: A pointer to the name of the opcode (ASCII String) - * Note: Never returns NULL. - * - * DESCRIPTION: Translate an opcode into a human-readable string - * - ******************************************************************************/ - -char *acpi_ps_get_opcode_name(u16 opcode) -{ -#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) - - const struct acpi_opcode_info *op; - - op = acpi_ps_get_opcode_info(opcode); - - /* Always guaranteed to return a valid pointer */ - - return (op->name); - -#else - return ("OpcodeName unavailable"); - -#endif -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_get_argument_count - * - * PARAMETERS: op_type - Type associated with the AML opcode - * - * RETURN: Argument count - * - * DESCRIPTION: Obtain the number of expected arguments for an AML opcode - * - ******************************************************************************/ - -u8 acpi_ps_get_argument_count(u32 op_type) -{ - - if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { - return (acpi_gbl_argument_count[op_type]); - } - - return (0); -} diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c new file mode 100644 index 000000000000..9ba5301e5751 --- /dev/null +++ b/drivers/acpi/acpica/psopinfo.c @@ -0,0 +1,223 @@ +/****************************************************************************** + * + * Module Name: psopinfo - AML opcode information functions and dispatch tables + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acparser.h" +#include "acopcode.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER +ACPI_MODULE_NAME("psopinfo") + +extern const u8 acpi_gbl_short_op_index[]; +extern const u8 acpi_gbl_long_op_index[]; + +static const u8 acpi_gbl_argument_count[] = + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_info + * + * PARAMETERS: opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. + * + * DESCRIPTION: Find AML opcode description based on the opcode. + * NOTE: This procedure must ALWAYS return a valid pointer! + * + ******************************************************************************/ + +const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) +{ + ACPI_FUNCTION_NAME(ps_get_opcode_info); + + /* + * Detect normal 8-bit opcode or extended 16-bit opcode + */ + if (!(opcode & 0xFF00)) { + + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_short_op_index[(u8)opcode]]); + } + + if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && + (((u8)opcode) <= MAX_EXTENDED_OPCODE)) { + + /* Valid extended (16-bit) opcode */ + + return (&acpi_gbl_aml_op_info + [acpi_gbl_long_op_index[(u8)opcode]]); + } + + /* Unknown AML opcode */ + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Unknown AML opcode [%4.4X]\n", opcode)); + + return (&acpi_gbl_aml_op_info[_UNK]); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_opcode_name + * + * PARAMETERS: opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +char *acpi_ps_get_opcode_name(u16 opcode) +{ +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) + + const struct acpi_opcode_info *op; + + op = acpi_ps_get_opcode_info(opcode); + + /* Always guaranteed to return a valid pointer */ + + return (op->name); + +#else + return ("OpcodeName unavailable"); + +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_ps_get_argument_count + * + * PARAMETERS: op_type - Type associated with the AML opcode + * + * RETURN: Argument count + * + * DESCRIPTION: Obtain the number of expected arguments for an AML opcode + * + ******************************************************************************/ + +u8 acpi_ps_get_argument_count(u32 op_type) +{ + + if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { + return (acpi_gbl_argument_count[op_type]); + } + + return (0); +} + +/* + * This table is directly indexed by the opcodes It returns + * an index into the opcode table (acpi_gbl_aml_op_info) + */ +const u8 acpi_gbl_short_op_index[256] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, +/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; + +/* + * This table is indexed by the second opcode of the extended opcode + * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info) + */ +const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = { +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, +}; diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 01985703bb98..abc4c48b2edd 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,9 +43,9 @@ /* * Parse the AML and build an operation tree as most interpreters, - * like Perl, do. Parsing is done by hand rather than with a YACC + * like Perl, do. Parsing is done by hand rather than with a YACC * generated parser to tightly constrain stack and dynamic memory - * usage. At the same time, parsing is kept flexible and the code + * usage. At the same time, parsing is kept flexible and the code * fairly compact by parsing based on a list of AML opcode * templates in aml_op_info[] */ @@ -379,7 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, case AE_CTRL_FALSE: /* * Either an IF/WHILE Predicate was false or we encountered a BREAK - * opcode. In both cases, we do not execute the rest of the + * opcode. In both cases, we do not execute the rest of the * package; We simply close out the parent (finishing the walk of * this branch of the tree) and continue execution at the parent * level. @@ -459,8 +459,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) /* Executing a control method - additional cleanup */ - acpi_ds_terminate_control_method( - walk_state->method_desc, walk_state); + acpi_ds_terminate_control_method(walk_state-> + method_desc, + walk_state); } acpi_ds_delete_walk_state(walk_state); @@ -487,7 +488,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) acpi_gbl_current_walk_list = thread; /* - * Execute the walk loop as long as there is a valid Walk State. This + * Execute the walk loop as long as there is a valid Walk State. This * handles nested control method invocations without recursion. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state)); diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index 608dc20dc173..6a4b6fb39f32 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index fdb2e71f3046..c1934bf04f0a 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index 8736ad5f04d3..91fa73a6e55e 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +108,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) * RETURN: Pointer to the new Op, null on failure * * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on - * opcode. A cache of opcodes is available for the pure + * opcode. A cache of opcodes is available for the pure * GENERIC_OP, since this is by far the most commonly used. * ******************************************************************************/ @@ -164,7 +164,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) * * RETURN: None. * - * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list + * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list * or actually free it. * ******************************************************************************/ @@ -202,14 +202,6 @@ u8 acpi_ps_is_leading_char(u32 c) } /* - * Is "c" a namestring prefix character? - */ -u8 acpi_ps_is_prefix_char(u32 c) -{ - return ((u8) (c == '\\' || c == '^')); -} - -/* * Get op's name (4-byte name segment) or 0 if unnamed */ #ifdef ACPI_FUTURE_USAGE diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index ab96cf47896d..abd65624754f 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index 963e16225797..f68254268965 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index 856ff075b6ab..f3a9276ac665 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index de12469d1c9c..7816d4eef04e 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,7 +84,7 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) bit_field &= (u16) (bit_field - 1); } - return bits_set; + return (bits_set); } /******************************************************************************* @@ -407,7 +407,9 @@ acpi_rs_get_list_length(u8 * aml_buffer, /* Validate the Resource Type and Resource Length */ - status = acpi_ut_validate_resource(aml_buffer, &resource_index); + status = + acpi_ut_validate_resource(NULL, aml_buffer, + &resource_index); if (ACPI_FAILURE(status)) { /* * Exit on failure. Cannot continue because the descriptor length @@ -457,6 +459,15 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Get the number of vendor data bytes */ extra_struct_bytes = resource_length; + + /* + * There is already one byte included in the minimum + * descriptor size. If there are extra struct bytes, + * subtract one from the count. + */ + if (extra_struct_bytes) { + extra_struct_bytes--; + } break; case ACPI_RESOURCE_NAME_END_TAG: @@ -601,7 +612,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, /* * Calculate the size of the return buffer. * The base size is the number of elements * the sizes of the - * structures. Additional space for the strings is added below. + * structures. Additional space for the strings is added below. * The minus one is to subtract the size of the u8 Source[1] * member because it is added below. * @@ -664,8 +675,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, (*sub_object_list)->string. length + 1); } else { - temp_size_needed += - acpi_ns_get_pathname_length((*sub_object_list)->reference.node); + temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node); } } else { /* diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 311cbc4f05fa..f8b55b426c9d 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,7 +98,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, /* Perform the AML-to-Resource conversion */ - status = acpi_ut_walk_aml_resources(aml_buffer, aml_buffer_length, + status = acpi_ut_walk_aml_resources(NULL, aml_buffer, aml_buffer_length, acpi_rs_convert_aml_to_resources, ¤t_resource_ptr); if (status == AE_AML_NO_RESOURCE_END_TAG) { @@ -174,7 +174,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, /* Do the conversion */ resource = output_buffer->pointer; - status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, + status = acpi_ut_walk_aml_resources(NULL, aml_start, aml_buffer_length, acpi_rs_convert_aml_to_resources, &resource); if (ACPI_FAILURE(status)) { @@ -480,8 +480,7 @@ acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer, status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", - (u32) aml_size_needed, - acpi_format_exception(status))); + (u32)aml_size_needed, acpi_format_exception(status))); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index 4d11b072388c..cab51445189d 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,419 +77,16 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource); static void acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); -#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) -#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) -#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) - -/******************************************************************************* - * - * Resource Descriptor info tables - * - * Note: The first table entry must be a Title or Literal and must contain - * the table length (number of table entries) - * - ******************************************************************************/ - -struct acpi_rsdump_info acpi_rs_dump_irq[7] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_dma[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", - acpi_gbl_typ_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", - acpi_gbl_bm_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", - acpi_gbl_siz_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", - NULL}, - {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), - "Start-Dependent-Functions", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), - "Descriptor Length", NULL}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), - "Compatibility Priority", acpi_gbl_config_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), - "Performance/Robustness", acpi_gbl_config_decode} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), - "End-Dependent-Functions", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_io[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", - acpi_gbl_io_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), - "Fixed I/O", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), - "Vendor Specific", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, - {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", - NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), - "24-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), - "32-Bit Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), - "32-Bit Fixed Memory Range", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), - "Address Length", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address16[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), - "16-Bit WORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address32[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), - "32-Bit DWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), - "64-Bit QWORD Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", - NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), - "64-Bit Extended Address Space", NULL}, - {ACPI_RSD_ADDRESS, 0, NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), - "Granularity", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), - "Address Minimum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), - "Address Maximum", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), - "Translation Offset", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), - "Address Length", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), - "Type-Specific Attribute", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), - "Extended IRQ", NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), - "Type", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), - "Triggering", acpi_gbl_he_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", - acpi_gbl_shr_decode}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), - "Interrupt Count", NULL}, - {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), - "Interrupt List", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), - "Generic Register", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), - "Access Size", NULL}, - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} -}; - -struct acpi_rsdump_info acpi_rs_dump_gpio[16] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type), - "ConnectionType", acpi_gbl_ct_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer), - "ProducerConsumer", acpi_gbl_consume_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig", - acpi_gbl_ppc_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharable", - acpi_gbl_shr_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction), - "IoRestriction", acpi_gbl_ior_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering", - acpi_gbl_he_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity", - acpi_gbl_ll_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength", - NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout), - "DebounceTimeout", NULL}, - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source), - "ResourceSource", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length), - "PinTableLength", NULL}, - {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength", - NULL}, - {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData", - NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma), - "FixedDma", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines), - "RequestLines", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels", - NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth", - acpi_gbl_dts_decode}, -}; - -#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \ - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \ - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \ - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \ - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \ - {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \ - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \ - {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL}, - -struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus), - "Common Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS -}; - -struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus), - "I2C Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, - ACPI_RSD_OFFSET(i2c_serial_bus. - access_mode), - "AccessMode", acpi_gbl_am_decode}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed), - "ConnectionSpeed", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address), - "SlaveAddress", NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus), - "Spi Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, - ACPI_RSD_OFFSET(spi_serial_bus. - wire_mode), "WireMode", - acpi_gbl_wm_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity), - "DevicePolarity", acpi_gbl_dp_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length), - "DataBitLength", NULL}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase), - "ClockPhase", acpi_gbl_cph_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity), - "ClockPolarity", acpi_gbl_cpo_decode}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection), - "DeviceSelection", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed), - "ConnectionSpeed", NULL}, -}; - -struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus), - "Uart Serial Bus", NULL}, - ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG, - ACPI_RSD_OFFSET(uart_serial_bus. - flow_control), - "FlowControl", acpi_gbl_fc_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits), - "StopBits", acpi_gbl_sb_decode}, - {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits), - "DataBits", acpi_gbl_bpb_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian", - acpi_gbl_ed_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity", - acpi_gbl_pt_decode}, - {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled), - "LinesEnabled", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size), - "RxFifoSize", NULL}, - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size), - "TxFifoSize", NULL}, - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate), - "ConnectionSpeed", NULL}, -}; - -/* - * Tables used for common address descriptor flag fields - */ -static struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, - NULL}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), - "Consumer/Producer", acpi_gbl_consume_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", - acpi_gbl_dec_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), - "Min Relocatability", acpi_gbl_min_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), - "Max Relocatability", acpi_gbl_max_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), - "Resource Type", (void *)"Memory Range"}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), - "Write Protect", acpi_gbl_rw_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), - "Caching", acpi_gbl_mem_decode}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), - "Range Type", acpi_gbl_mtp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), - "Translation", acpi_gbl_ttp_decode} -}; - -static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { - {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), - "Resource Type", (void *)"I/O Range"}, - {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), - "Range Type", acpi_gbl_rng_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), - "Translation", acpi_gbl_ttp_decode}, - {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), - "Translation Type", acpi_gbl_trs_decode} -}; - -/* - * Table used to dump _PRT contents - */ -static struct acpi_rsdump_info acpi_rs_dump_prt[5] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, - {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, - {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, - {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} -}; - /******************************************************************************* * * FUNCTION: acpi_rs_dump_descriptor * - * PARAMETERS: Resource + * PARAMETERS: resource - Buffer containing the resource + * table - Table entry to decode the resource * * RETURN: None * - * DESCRIPTION: + * DESCRIPTION: Dump a resource descriptor based on a dump table entry. * ******************************************************************************/ @@ -654,7 +251,8 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* * Optional resource_source for Address resources */ - acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct + acpi_rs_dump_resource_source(ACPI_CAST_PTR + (struct acpi_resource_source, target)); break; @@ -765,8 +363,9 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) ACPI_FUNCTION_ENTRY(); - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) { return; } @@ -827,8 +426,9 @@ void acpi_rs_dump_irq_list(u8 * route_table) ACPI_FUNCTION_ENTRY(); - if (!(acpi_dbg_level & ACPI_LV_RESOURCES) - || !(_COMPONENT & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(ACPI_LV_RESOURCES, _COMPONENT)) { return; } diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c new file mode 100644 index 000000000000..46192bd53653 --- /dev/null +++ b/drivers/acpi/acpica/rsdumpinfo.c @@ -0,0 +1,454 @@ +/******************************************************************************* + * + * Module Name: rsdumpinfo - Tables used to display resource descriptors. + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES +ACPI_MODULE_NAME("rsdumpinfo") + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +#define ACPI_RSD_OFFSET(f) (u8) ACPI_OFFSET (union acpi_resource_data,f) +#define ACPI_PRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_pci_routing_table,f) +#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (struct acpi_rsdump_info)) +/******************************************************************************* + * + * Resource Descriptor info tables + * + * Note: The first table entry must be a Title or Literal and must contain + * the table length (number of table entries) + * + ******************************************************************************/ +struct acpi_rsdump_info acpi_rs_dump_irq[7] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_dma[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", + acpi_gbl_typ_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", + acpi_gbl_bm_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", + acpi_gbl_siz_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", + NULL}, + {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), + "Start-Dependent-Functions", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), + "Descriptor Length", NULL}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), + "Compatibility Priority", acpi_gbl_config_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), + "Performance/Robustness", acpi_gbl_config_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_dpf[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_dpf), + "End-Dependent-Functions", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_io[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io), "I/O", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(io.io_decode), "Address Decoding", + acpi_gbl_io_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(io.maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.alignment), "Alignment", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(io.address_length), "Address Length", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_io[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_io), + "Fixed I/O", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_io.address), "Address", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_io.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_vendor[3] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_vendor), + "Vendor Specific", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(vendor.byte_length), "Length", NULL}, + {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET(vendor.byte_data[0]), "Vendor Data", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", + NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory24[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), + "24-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory32[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), + "32-Bit Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.alignment), "Alignment", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_memory32[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), + "32-Bit Fixed Memory Range", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), + "Address Length", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address16[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16), + "16-Bit WORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address32[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32), + "32-Bit DWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64), + "64-Bit QWORD Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum", + NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64), + "64-Bit Extended Address Space", NULL}, + {ACPI_RSD_ADDRESS, 0, NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity), + "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum), + "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum), + "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length), + "Address Length", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific), + "Type-Specific Attribute", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_ext_irq[8] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_irq), + "Extended IRQ", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), + "Type", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), + "Triggering", acpi_gbl_he_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), + "Interrupt Count", NULL}, + {ACPI_RSD_DWORDLIST, ACPI_RSD_OFFSET(extended_irq.interrupts[0]), + "Interrupt List", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_generic_reg), + "Generic Register", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.space_id), "Space ID", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_width), "Bit Width", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.bit_offset), "Bit Offset", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(generic_reg.access_size), + "Access Size", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL} +}; + +struct acpi_rsdump_info acpi_rs_dump_gpio[16] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type), + "ConnectionType", acpi_gbl_ct_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer), + "ProducerConsumer", acpi_gbl_consume_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig", + acpi_gbl_ppc_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharing", + acpi_gbl_shr_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction), + "IoRestriction", acpi_gbl_ior_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering", + acpi_gbl_he_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity", + acpi_gbl_ll_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength", + NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout), + "DebounceTimeout", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source), + "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length), + "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength", + NULL}, + {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData", + NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma), + "FixedDma", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines), + "RequestLines", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels", + NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth", + acpi_gbl_dts_decode}, +}; + +#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \ + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \ + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \ + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \ + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \ + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL}, + +struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus), + "Common Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS +}; + +struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus), + "I2C Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, + ACPI_RSD_OFFSET(i2c_serial_bus. + access_mode), + "AccessMode", acpi_gbl_am_decode}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed), + "ConnectionSpeed", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address), + "SlaveAddress", NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus), + "Spi Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG, + ACPI_RSD_OFFSET(spi_serial_bus. + wire_mode), "WireMode", + acpi_gbl_wm_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity), + "DevicePolarity", acpi_gbl_dp_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length), + "DataBitLength", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase), + "ClockPhase", acpi_gbl_cph_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity), + "ClockPolarity", acpi_gbl_cpo_decode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection), + "DeviceSelection", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed), + "ConnectionSpeed", NULL}, +}; + +struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus), + "Uart Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG, + ACPI_RSD_OFFSET(uart_serial_bus. + flow_control), + "FlowControl", acpi_gbl_fc_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits), + "StopBits", acpi_gbl_sb_decode}, + {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits), + "DataBits", acpi_gbl_bpb_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian", + acpi_gbl_ed_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity", + acpi_gbl_pt_decode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled), + "LinesEnabled", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size), + "RxFifoSize", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size), + "TxFifoSize", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate), + "ConnectionSpeed", NULL}, +}; + +/* + * Tables used for common address descriptor flag fields + */ +struct acpi_rsdump_info acpi_rs_dump_general_flags[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_general_flags), NULL, + NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), + "Consumer/Producer", acpi_gbl_consume_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", + acpi_gbl_dec_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), + "Min Relocatability", acpi_gbl_min_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), + "Max Relocatability", acpi_gbl_max_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_memory_flags[5] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), + "Resource Type", (void *)"Memory Range"}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), + "Write Protect", acpi_gbl_rw_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), + "Caching", acpi_gbl_mem_decode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), + "Range Type", acpi_gbl_mtp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), + "Translation", acpi_gbl_ttp_decode} +}; + +struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { + {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), + "Resource Type", (void *)"I/O Range"}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), + "Range Type", acpi_gbl_rng_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), + "Translation", acpi_gbl_ttp_decode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), + "Translation Type", acpi_gbl_trs_decode} +}; + +/* + * Table used to dump _PRT contents + */ +struct acpi_rsdump_info acpi_rs_dump_prt[5] = { + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_prt), NULL, NULL}, + {ACPI_RSD_UINT64, ACPI_PRT_OFFSET(address), "Address", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(pin), "Pin", NULL}, + {ACPI_RSD_STRING, ACPI_PRT_OFFSET(source[0]), "Source", NULL}, + {ACPI_RSD_UINT32, ACPI_PRT_OFFSET(source_index), "Source Index", NULL} +}; + +#endif diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c index a9fa5158200b..41fed78e0de6 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index f6a081057a22..ca183755a6f9 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c index e23a9ec248cb..364decc1028a 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsirq") * acpi_rs_get_irq * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_get_irq[8] = { +struct acpi_rsconvert_info acpi_rs_get_irq[9] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, ACPI_RS_SIZE(struct acpi_resource_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, @@ -80,7 +80,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, - /* Get flags: Triggering[0], Polarity[3], Sharing[4] */ + /* Get flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -92,7 +92,11 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), AML_OFFSET(irq.flags), - 4} + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.wake_capable), + AML_OFFSET(irq.flags), + 5} }; /******************************************************************************* @@ -101,7 +105,7 @@ struct acpi_rsconvert_info acpi_rs_get_irq[8] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_set_irq[13] = { +struct acpi_rsconvert_info acpi_rs_set_irq[14] = { /* Start with a default descriptor of length 3 */ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, @@ -114,7 +118,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { AML_OFFSET(irq.irq_mask), ACPI_RS_OFFSET(data.irq.interrupt_count)}, - /* Set the flags byte */ + /* Set flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), AML_OFFSET(irq.flags), @@ -128,6 +132,10 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { AML_OFFSET(irq.flags), 4}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.wake_capable), + AML_OFFSET(irq.flags), + 5}, + /* * All done if the output descriptor length is required to be 3 * (i.e., optimization to 2 bytes cannot be attempted) @@ -181,7 +189,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[13] = { * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { +struct acpi_rsconvert_info acpi_rs_convert_ext_irq[10] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ, ACPI_RS_SIZE(struct acpi_resource_extended_irq), ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_irq)}, @@ -190,8 +198,10 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { sizeof(struct aml_resource_extended_irq), 0}, - /* Flag bits */ - + /* + * Flags: Producer/Consumer[0], Triggering[1], Polarity[2], + * Sharing[3], Wake[4] + */ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.producer_consumer), AML_OFFSET(extended_irq.flags), 0}, @@ -208,19 +218,21 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_irq[9] = { AML_OFFSET(extended_irq.flags), 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.extended_irq.wake_capable), + AML_OFFSET(extended_irq.flags), + 4}, + /* IRQ Table length (Byte4) */ {ACPI_RSC_COUNT, ACPI_RS_OFFSET(data.extended_irq.interrupt_count), AML_OFFSET(extended_irq.interrupt_count), - sizeof(u32)} - , + sizeof(u32)}, /* Copy every IRQ in the table, each is 32 bits */ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.extended_irq.interrupts[0]), AML_OFFSET(extended_irq.interrupts[0]), - 0} - , + 0}, /* Optional resource_source (Index and String) */ @@ -285,7 +297,6 @@ struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { * request_lines * Channels */ - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_dma.request_lines), AML_OFFSET(fixed_dma.request_lines), 2}, @@ -293,5 +304,4 @@ struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = { {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_dma.width), AML_OFFSET(fixed_dma.width), 1}, - }; diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 46b5324b22d6..ee2e206fc6c8 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,7 +109,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, ACPI_ERROR((AE_INFO, "Invalid/unsupported resource descriptor: Type 0x%2.2X", resource_index)); - return (AE_AML_INVALID_RESOURCE_TYPE); + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); } /* Convert the AML byte stream resource to a local resource struct */ @@ -200,7 +200,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, ACPI_ERROR((AE_INFO, "Invalid/unsupported resource descriptor: Type 0x%2.2X", resource->type)); - return (AE_AML_INVALID_RESOURCE_TYPE); + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); } status = acpi_rs_convert_resource_to_aml(resource, @@ -217,9 +217,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Perform final sanity check on the new AML resource descriptor */ - status = - acpi_ut_validate_resource(ACPI_CAST_PTR - (union aml_resource, aml), NULL); + status = acpi_ut_validate_resource(NULL, + ACPI_CAST_PTR(union + aml_resource, + aml), NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index 4fd611ad02b4..ebc773a1b350 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -156,8 +156,7 @@ struct acpi_rsconvert_info acpi_rs_get_vendor_small[3] = { {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), 0, - sizeof(u8)} - , + sizeof(u8)}, /* Vendor data */ @@ -181,8 +180,7 @@ struct acpi_rsconvert_info acpi_rs_get_vendor_large[3] = { {ACPI_RSC_COUNT16, ACPI_RS_OFFSET(data.vendor.byte_length), 0, - sizeof(u8)} - , + sizeof(u8)}, /* Vendor data */ diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index c6f291c2bc83..d5bf05a96096 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,30 +136,30 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, /* * Mask and shift the flag bit */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x01); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x01)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x03); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x03)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) = (u8) - ((ACPI_GET8(source) >> info->value) & 0x07); + ACPI_SET8(destination, + ((ACPI_GET8(source) >> info->value) & 0x07)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; + ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); @@ -168,7 +168,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, case ACPI_RSC_COUNT16: item_count = aml_resource_length; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); @@ -181,13 +181,13 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, resource->length = resource->length + item_count; item_count = item_count / 2; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8)item_count; + ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * item_count); @@ -216,7 +216,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_VEN: @@ -224,7 +224,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, item_count = ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_RES: @@ -234,7 +234,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, - ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; - ACPI_SET16(destination) = item_count; + ACPI_SET16(destination, item_count); break; case ACPI_RSC_LENGTH: @@ -385,7 +385,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; + ACPI_SET8(target, item_count); break; case ACPI_RSC_BITMASK16: @@ -401,7 +401,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, } target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_SET8(target) = (u8) item_count; + ACPI_SET8(target, item_count); break; case ACPI_RSC_EXIT_NE: @@ -514,37 +514,40 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * Clear the flag byte */ - ACPI_SET8(destination) = 0; + ACPI_SET8(destination, 0); break; case ACPI_RSC_1BITFLAG: /* * Mask and shift the flag bit */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x01) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x01) << info-> + value)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x03) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x03) << info-> + value)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ - ACPI_SET8(destination) |= (u8) - ((ACPI_GET8(source) & 0x07) << info->value); + ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) + ((ACPI_GET8(source) & 0x07) << info-> + value)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); - ACPI_SET8(destination) = (u8) item_count; + ACPI_SET8(destination, item_count); aml_length = (u16) (aml_length + @@ -561,18 +564,18 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_COUNT_GPIO_PIN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)aml_length; + ACPI_SET16(destination, aml_length); aml_length = (u16)(aml_length + item_count * 2); target = ACPI_ADD_PTR(void, aml, info->value); - ACPI_SET16(target) = (u16)aml_length; + ACPI_SET16(target, aml_length); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)item_count; + ACPI_SET16(destination, item_count); aml_length = (u16)(aml_length + (info->value * item_count)); @@ -584,7 +587,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* Set resource source string length */ item_count = ACPI_GET16(source); - ACPI_SET16(destination) = (u16)aml_length; + ACPI_SET16(destination, aml_length); /* Compute offset for the Vendor Data */ @@ -594,7 +597,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* Set vendor offset only if there is vendor data */ if (resource->data.gpio.vendor_length) { - ACPI_SET16(target) = (u16)aml_length; + ACPI_SET16(target, aml_length); } acpi_rs_set_resource_length(aml_length, aml); @@ -603,7 +606,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, case ACPI_RSC_COUNT_SERIAL_VEN: item_count = ACPI_GET16(source); - ACPI_SET16(destination) = item_count + info->value; + ACPI_SET16(destination, item_count + info->value); aml_length = (u16)(aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; @@ -686,7 +689,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, * Optional resource_source (Index and String) */ aml_length = - acpi_rs_set_resource_source(aml, (acpi_rs_length) + acpi_rs_set_resource_source(aml, + (acpi_rs_length) aml_length, source); acpi_rs_set_resource_length(aml_length, aml); break; @@ -706,10 +710,12 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * 8-bit encoded bitmask (DMA macro) */ - ACPI_SET8(destination) = (u8) - acpi_rs_encode_bitmask(source, - *ACPI_ADD_PTR(u8, resource, - info->value)); + ACPI_SET8(destination, + acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, + resource, + info-> + value))); break; case ACPI_RSC_BITMASK16: diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c index 9aa5e689b444..fe49fc43e10f 100644 --- a/drivers/acpi/acpica/rsserial.c +++ b/drivers/acpi/acpica/rsserial.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsserial") * acpi_rs_convert_gpio * ******************************************************************************/ -struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = { +struct acpi_rsconvert_info acpi_rs_convert_gpio[18] = { {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO, ACPI_RS_SIZE(struct acpi_resource_gpio), ACPI_RSC_TABLE_SIZE(acpi_rs_convert_gpio)}, @@ -75,10 +75,14 @@ struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = { AML_OFFSET(gpio.flags), 0}, - {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable), + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable), AML_OFFSET(gpio.int_flags), 3}, + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.wake_capable), + AML_OFFSET(gpio.int_flags), + 4}, + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.io_restriction), AML_OFFSET(gpio.int_flags), 0}, diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 37d5241c0acf..a44953c6f75d 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +108,7 @@ u16 acpi_rs_encode_bitmask(u8 * list, u8 count) mask |= (0x1 << list[i]); } - return mask; + return (mask); } /******************************************************************************* @@ -358,8 +358,10 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * * Zero the entire area of the buffer. */ - total_length = (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; + total_length = + (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); ACPI_MEMSET(resource_source->string_ptr, 0, total_length); @@ -675,7 +677,9 @@ acpi_rs_get_method_data(acpi_handle handle, /* Execute the method, no parameters */ status = - acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc); + acpi_ut_evaluate_object(ACPI_CAST_PTR + (struct acpi_namespace_node, handle), path, + ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 5aad744b5b83..15d6eaef0e28 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -423,7 +423,7 @@ ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) * * RETURN: Status * - * DESCRIPTION: Walk a resource template for the specified evice to find a + * DESCRIPTION: Walk a resource template for the specified device to find a * vendor-defined resource that matches the supplied UUID and * UUID subtype. Returns a struct acpi_resource of type Vendor. * @@ -522,57 +522,42 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) /******************************************************************************* * - * FUNCTION: acpi_walk_resources + * FUNCTION: acpi_walk_resource_buffer * - * PARAMETERS: device_handle - Handle to the device object for the - * device we are querying - * name - Method name of the resources we want. - * (METHOD_NAME__CRS, METHOD_NAME__PRS, or - * METHOD_NAME__AEI) + * PARAMETERS: buffer - Formatted buffer returned by one of the + * various Get*Resource functions * user_function - Called for each resource * context - Passed to user_function * * RETURN: Status * - * DESCRIPTION: Retrieves the current or possible resource list for the - * specified device. The user_function is called once for - * each resource in the list. + * DESCRIPTION: Walks the input resource template. The user_function is called + * once for each resource in the list. * ******************************************************************************/ + acpi_status -acpi_walk_resources(acpi_handle device_handle, - char *name, - acpi_walk_resource_callback user_function, void *context) +acpi_walk_resource_buffer(struct acpi_buffer * buffer, + acpi_walk_resource_callback user_function, + void *context) { - acpi_status status; - struct acpi_buffer buffer; + acpi_status status = AE_OK; struct acpi_resource *resource; struct acpi_resource *resource_end; - ACPI_FUNCTION_TRACE(acpi_walk_resources); + ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer); /* Parameter validation */ - if (!device_handle || !user_function || !name || - (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && - !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) { + if (!buffer || !buffer->pointer || !user_function) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get the _CRS/_PRS/_AEI resource list */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_get_method_data(device_handle, name, &buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Buffer now contains the resource list */ + /* Buffer contains the resource list and length */ - resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer); resource_end = - ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); + ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length); /* Walk the resource list until the end_tag is found (or buffer end) */ @@ -606,11 +591,63 @@ acpi_walk_resources(acpi_handle device_handle, /* Get the next resource descriptor */ - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); + resource = ACPI_NEXT_RESOURCE(resource); } + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer) + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * name - Method name of the resources we want. + * (METHOD_NAME__CRS, METHOD_NAME__PRS, or + * METHOD_NAME__AEI) + * user_function - Called for each resource + * context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ +acpi_status +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_TRACE(acpi_walk_resources); + + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the _CRS/_PRS/_AEI resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Walk the resource list and cleanup */ + + status = acpi_walk_resource_buffer(&buffer, user_function, context); ACPI_FREE(buffer.pointer); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 390651860bf0..74181bf181ec 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -172,6 +172,7 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { * FUNCTION: acpi_tb_init_generic_address * * PARAMETERS: generic_address - GAS struct to be initialized + * space_id - ACPI Space ID for this register * byte_width - Width of this register * address - Address of the register * @@ -407,8 +408,8 @@ static void acpi_tb_convert_fadt(void) * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * - * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at - * offset 45, 55, 95, and the word located at offset 109, 110. + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located + * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index 57deae166577..e4f4f02d49e7 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,7 +77,7 @@ acpi_tb_find_table(char *signature, /* Normalize the input strings */ ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); - ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); + ACPI_MOVE_NAME(header.signature, signature); ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 70f9d787c82c..e57cd38004e3 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -526,6 +526,8 @@ void acpi_tb_terminate(void) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + return_VOID; } /******************************************************************************* diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index b6cea30da638..ce3d5db39a9c 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -147,7 +147,7 @@ acpi_status acpi_tb_initialize_facs(void) ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, &acpi_gbl_FACS)); - return status; + return (status); } #endif /* !ACPI_REDUCED_HARDWARE */ @@ -354,7 +354,7 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) sum = (u8) (sum + *(buffer++)); } - return sum; + return (sum); } /******************************************************************************* diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 21101262e47a..b35a5e6d653a 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,6 @@ #include <linux/export.h> #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #include "actables.h" #define _COMPONENT ACPI_TABLES @@ -236,7 +235,7 @@ acpi_get_table_header(char *signature, sizeof(struct acpi_table_header)); if (!header) { - return AE_NO_MEMORY; + return (AE_NO_MEMORY); } ACPI_MEMCPY(out_table_header, header, sizeof(struct acpi_table_header)); @@ -244,7 +243,7 @@ acpi_get_table_header(char *signature, sizeof(struct acpi_table_header)); } else { - return AE_NOT_FOUND; + return (AE_NOT_FOUND); } } else { ACPI_MEMCPY(out_table_header, @@ -437,7 +436,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) * ******************************************************************************/ acpi_status -acpi_install_table_handler(acpi_tbl_handler handler, void *context) +acpi_install_table_handler(acpi_table_handler handler, void *context) { acpi_status status; @@ -483,7 +482,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_table_handler) * DESCRIPTION: Remove table event handler * ******************************************************************************/ -acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +acpi_status acpi_remove_table_handler(acpi_table_handler handler) { acpi_status status; diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index f87cc63e69a1..67e046ec8f0a 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -192,7 +192,7 @@ static acpi_status acpi_tb_load_namespace(void) (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); @@ -211,7 +211,7 @@ static acpi_status acpi_tb_load_namespace(void) * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must * be a valid ACPI table with a valid ACPI table header. * Note1: Mainly intended to support hotplug addition of SSDTs. - * Note2: Does not copy the incoming table. User is reponsible + * Note2: Does not copy the incoming table. User is responsible * to ensure that the table is not deleted or unmapped. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 74e720800037..7c2ecfb7c2c3 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,7 +67,6 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) { - ACPI_FUNCTION_ENTRY(); /* * The signature and checksum must both be correct @@ -108,7 +107,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * RETURN: Status, RSDP physical address * * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor - * pointer structure. If it is found, set *RSDP to point to it. + * pointer structure. If it is found, set *RSDP to point to it. * * NOTE1: The RSDP must be either in the first 1K of the Extended * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c index 64880306133d..698b9d385516 100644 --- a/drivers/acpi/acpica/utaddress.c +++ b/drivers/acpi/acpica/utaddress.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -214,7 +214,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { - return_UINT32(0); + return_VALUE(0); } range_info = acpi_gbl_address_range_list[space_id]; @@ -256,7 +256,7 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, range_info = range_info->next; } - return_UINT32(overlap_count); + return_VALUE(overlap_count); } /******************************************************************************* diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index ed29d474095e..e0ffb580f4b0 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c new file mode 100644 index 000000000000..e0e8579deaac --- /dev/null +++ b/drivers/acpi/acpica/utcache.c @@ -0,0 +1,323 @@ +/****************************************************************************** + * + * Module Name: utcache - local cache allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utcache") + +#ifdef ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: acpi_os_create_cache + * + * PARAMETERS: cache_name - Ascii name for the cache + * object_size - Size of each cached object + * max_depth - Maximum depth of the cache (in objects) + * return_cache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ +acpi_status +acpi_os_create_cache(char *cache_name, + u16 object_size, + u16 max_depth, struct acpi_memory_list ** return_cache) +{ + struct acpi_memory_list *cache; + + ACPI_FUNCTION_ENTRY(); + + if (!cache_name || !return_cache || (object_size < 16)) { + return (AE_BAD_PARAMETER); + } + + /* Create the cache object */ + + cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); + if (!cache) { + return (AE_NO_MEMORY); + } + + /* Populate the cache object and return it */ + + ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); + cache->link_offset = 8; + cache->list_name = cache_name; + cache->object_size = object_size; + cache->max_depth = max_depth; + + *return_cache = cache; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_purge_cache + * + * PARAMETERS: cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache) +{ + char *next; + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + if (!cache) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Walk the list of objects in this cache */ + + while (cache->list_head) { + + /* Delete and unlink one cached state object */ + + next = *(ACPI_CAST_INDIRECT_PTR(char, + &(((char *)cache-> + list_head)[cache-> + link_offset]))); + ACPI_FREE(cache->list_head); + + cache->list_head = next; + cache->current_depth--; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_delete_cache + * + * PARAMETERS: cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + /* Purge all objects in the cache */ + + status = acpi_os_purge_cache(cache); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Now we can delete the cache object */ + + acpi_os_free(cache); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_release_object + * + * PARAMETERS: cache - Handle to cache object + * object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +acpi_status +acpi_os_release_object(struct acpi_memory_list * cache, void *object) +{ + acpi_status status; + + ACPI_FUNCTION_ENTRY(); + + if (!cache || !object) { + return (AE_BAD_PARAMETER); + } + + /* If cache is full, just free this object */ + + if (cache->current_depth >= cache->max_depth) { + ACPI_FREE(object); + ACPI_MEM_TRACKING(cache->total_freed++); + } + + /* Otherwise put this object back into the cache */ + + else { + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Mark the object as cached */ + + ACPI_MEMSET(object, 0xCA, cache->object_size); + ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED); + + /* Put the object at the head of the cache list */ + + *(ACPI_CAST_INDIRECT_PTR(char, + &(((char *)object)[cache-> + link_offset]))) = + cache->list_head; + cache->list_head = object; + cache->current_depth++; + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_acquire_object + * + * PARAMETERS: cache - Handle to cache object + * + * RETURN: the acquired object. NULL on error + * + * DESCRIPTION: Get an object from the specified cache. If cache is empty, + * the object is allocated. + * + ******************************************************************************/ + +void *acpi_os_acquire_object(struct acpi_memory_list *cache) +{ + acpi_status status; + void *object; + + ACPI_FUNCTION_NAME(os_acquire_object); + + if (!cache) { + return (NULL); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (NULL); + } + + ACPI_MEM_TRACKING(cache->requests++); + + /* Check the cache first */ + + if (cache->list_head) { + + /* There is an object available, use it */ + + object = cache->list_head; + cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char, + &(((char *) + object)[cache-> + link_offset]))); + + cache->current_depth--; + + ACPI_MEM_TRACKING(cache->hits++); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Object %p from %s cache\n", object, + cache->list_name)); + + status = acpi_ut_release_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (NULL); + } + + /* Clear (zero) the previously used Object */ + + ACPI_MEMSET(object, 0, cache->object_size); + } else { + /* The cache is empty, create a new object */ + + ACPI_MEM_TRACKING(cache->total_allocated++); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + if ((cache->total_allocated - cache->total_freed) > + cache->max_occupied) { + cache->max_occupied = + cache->total_allocated - cache->total_freed; + } +#endif + + /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ + + status = acpi_ut_release_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return (NULL); + } + + object = ACPI_ALLOCATE_ZEROED(cache->object_size); + if (!object) { + return (NULL); + } + } + + return (object); +} +#endif /* ACPI_USE_LOCAL_CACHE */ diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 294692ae76e9..e4c9291fc0a3 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -785,7 +785,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { - return status; + return (status); } break; @@ -795,7 +795,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, &dest_desc->event. os_semaphore); if (ACPI_FAILURE(status)) { - return status; + return (status); } break; diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index e810894149ae..c57d9cc07ba9 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,8 +47,9 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdebug") + #ifdef ACPI_DEBUG_OUTPUT -static acpi_thread_id acpi_gbl_prev_thread_id; +static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF; static char *acpi_gbl_fn_entry_str = "----Entry"; static char *acpi_gbl_fn_exit_str = "----Exit-"; @@ -109,7 +110,7 @@ void acpi_ut_track_stack_ptr(void) * RETURN: Updated pointer to the function name * * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. - * This allows compiler macros such as __func__ to be used + * This allows compiler macros such as __FUNCTION__ to be used * with no change to the debug output. * ******************************************************************************/ @@ -165,11 +166,9 @@ acpi_debug_print(u32 requested_debug_level, acpi_thread_id thread_id; va_list args; - /* - * Stay silent if the debug level or component ID is disabled - */ - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(requested_debug_level, component_id)) { return; } @@ -222,7 +221,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print) * * RETURN: None * - * DESCRIPTION: Print message with no headers. Has same interface as + * DESCRIPTION: Print message with no headers. Has same interface as * debug_print so that the same macros can be used. * ******************************************************************************/ @@ -235,8 +234,9 @@ acpi_debug_print_raw(u32 requested_debug_level, { va_list args; - if (!(requested_debug_level & acpi_dbg_level) || - !(component_id & acpi_dbg_layer)) { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED(requested_debug_level, component_id)) { return; } @@ -258,7 +258,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print_raw) * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -271,9 +271,13 @@ acpi_ut_trace(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_entry_str); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s\n", acpi_gbl_fn_entry_str); + } } ACPI_EXPORT_SYMBOL(acpi_ut_trace) @@ -290,7 +294,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace) * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -299,12 +303,18 @@ acpi_ut_trace_ptr(u32 line_number, const char *function_name, const char *module_name, u32 component_id, void *pointer) { + acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_entry_str, pointer); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %p\n", acpi_gbl_fn_entry_str, + pointer); + } } /******************************************************************************* @@ -319,7 +329,7 @@ acpi_ut_trace_ptr(u32 line_number, * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -333,9 +343,14 @@ acpi_ut_trace_str(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %s\n", acpi_gbl_fn_entry_str, string); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %s\n", acpi_gbl_fn_entry_str, + string); + } } /******************************************************************************* @@ -350,7 +365,7 @@ acpi_ut_trace_str(u32 line_number, * * RETURN: None * - * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -364,9 +379,14 @@ acpi_ut_trace_u32(u32 line_number, acpi_gbl_nesting_level++; acpi_ut_track_stack_ptr(); - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %08X\n", acpi_gbl_fn_entry_str, integer); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %08X\n", + acpi_gbl_fn_entry_str, integer); + } } /******************************************************************************* @@ -380,7 +400,7 @@ acpi_ut_trace_u32(u32 line_number, * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level * ******************************************************************************/ @@ -391,9 +411,13 @@ acpi_ut_exit(u32 line_number, const char *module_name, u32 component_id) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s\n", acpi_gbl_fn_exit_str); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s\n", acpi_gbl_fn_exit_str); + } acpi_gbl_nesting_level--; } @@ -412,7 +436,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit) * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level. Prints exit status also. * ******************************************************************************/ @@ -423,17 +447,23 @@ acpi_ut_status_exit(u32 line_number, u32 component_id, acpi_status status) { - if (ACPI_SUCCESS(status)) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s %s\n", acpi_gbl_fn_exit_str, - acpi_format_exception(status)); - } else { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, - component_id, "%s ****Exception****: %s\n", - acpi_gbl_fn_exit_str, - acpi_format_exception(status)); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + if (ACPI_SUCCESS(status)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, + module_name, component_id, "%s %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } else { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, + module_name, component_id, + "%s ****Exception****: %s\n", + acpi_gbl_fn_exit_str, + acpi_format_exception(status)); + } } acpi_gbl_nesting_level--; @@ -453,7 +483,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level. Prints exit value also. * ******************************************************************************/ @@ -463,10 +493,15 @@ acpi_ut_value_exit(u32 line_number, const char *module_name, u32 component_id, u64 value) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str, - ACPI_FORMAT_UINT64(value)); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %8.8X%8.8X\n", + acpi_gbl_fn_exit_str, + ACPI_FORMAT_UINT64(value)); + } acpi_gbl_nesting_level--; } @@ -485,7 +520,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) * * RETURN: None * - * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is * set in debug_level. Prints exit value also. * ******************************************************************************/ @@ -495,9 +530,14 @@ acpi_ut_ptr_exit(u32 line_number, const char *module_name, u32 component_id, u8 *ptr) { - acpi_debug_print(ACPI_LV_FUNCTIONS, - line_number, function_name, module_name, component_id, - "%s %p\n", acpi_gbl_fn_exit_str, ptr); + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) { + acpi_debug_print(ACPI_LV_FUNCTIONS, + line_number, function_name, module_name, + component_id, "%s %p\n", acpi_gbl_fn_exit_str, + ptr); + } acpi_gbl_nesting_level--; } @@ -511,7 +551,7 @@ acpi_ut_ptr_exit(u32 line_number, * PARAMETERS: buffer - Buffer to dump * count - Amount to dump, in bytes * display - BYTE, WORD, DWORD, or QWORD display - * component_ID - Caller's component ID + * offset - Beginning buffer offset (display only) * * RETURN: None * @@ -519,7 +559,7 @@ acpi_ut_ptr_exit(u32 line_number, * ******************************************************************************/ -void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) +void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset) { u32 i = 0; u32 j; @@ -541,7 +581,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) /* Print current offset */ - acpi_os_printf("%6.4X: ", i); + acpi_os_printf("%6.4X: ", (base_offset + i)); /* Print 16 hex chars */ @@ -623,7 +663,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) /******************************************************************************* * - * FUNCTION: acpi_ut_dump_buffer + * FUNCTION: acpi_ut_debug_dump_buffer * * PARAMETERS: buffer - Buffer to dump * count - Amount to dump, in bytes @@ -636,7 +676,8 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) * ******************************************************************************/ -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) +void +acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) { /* Only dump the buffer if tracing is enabled */ @@ -646,5 +687,5 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) return; } - acpi_ut_dump_buffer2(buffer, count, display); + acpi_ut_dump_buffer(buffer, count, display, 0); } diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 60a158472d82..11e2e02e1618 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 798105443d0f..2541de420249 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -340,7 +340,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) { union acpi_operand_object **internal_obj; - ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); + ACPI_FUNCTION_ENTRY(); /* Walk the null-terminated internal list */ @@ -351,7 +351,7 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) /* Free the combined parameter pointer list and object array */ ACPI_FREE(obj_list); - return_VOID; + return; } /******************************************************************************* @@ -484,7 +484,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) union acpi_generic_state *state; u32 i; - ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); + ACPI_FUNCTION_NAME(ut_update_object_reference); while (object) { @@ -493,7 +493,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object)); - return_ACPI_STATUS(AE_OK); + return (AE_OK); } /* @@ -530,18 +530,42 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) */ for (i = 0; i < object->package.count; i++) { /* - * Push each element onto the stack for later processing. - * Note: There can be null elements within the package, - * these are simply ignored + * Null package elements are legal and can be simply + * ignored. */ - status = - acpi_ut_create_update_state_and_push - (object->package.elements[i], action, - &state_list); - if (ACPI_FAILURE(status)) { - goto error_exit; + next_object = object->package.elements[i]; + if (!next_object) { + continue; + } + + switch (next_object->common.type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + /* + * For these very simple sub-objects, we can just + * update the reference count here and continue. + * Greatly increases performance of this operation. + */ + acpi_ut_update_ref_count(next_object, + action); + break; + + default: + /* + * For complex sub-objects, push them onto the stack + * for later processing (this eliminates recursion.) + */ + status = + acpi_ut_create_update_state_and_push + (next_object, action, &state_list); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + break; } } + next_object = NULL; break; case ACPI_TYPE_BUFFER_FIELD: @@ -619,7 +643,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) } } - return_ACPI_STATUS(AE_OK); + return (AE_OK); error_exit: @@ -633,7 +657,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) acpi_ut_delete_generic_state(state); } - return_ACPI_STATUS(status); + return (status); } /******************************************************************************* @@ -652,12 +676,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) void acpi_ut_add_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); + ACPI_FUNCTION_NAME(ut_add_reference); /* Ensure that we have a valid object */ if (!acpi_ut_valid_internal_object(object)) { - return_VOID; + return; } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -667,7 +691,7 @@ void acpi_ut_add_reference(union acpi_operand_object *object) /* Increment the reference count */ (void)acpi_ut_update_object_reference(object, REF_INCREMENT); - return_VOID; + return; } /******************************************************************************* @@ -685,7 +709,7 @@ void acpi_ut_add_reference(union acpi_operand_object *object) void acpi_ut_remove_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); + ACPI_FUNCTION_NAME(ut_remove_reference); /* * Allow a NULL pointer to be passed in, just ignore it. This saves @@ -694,13 +718,13 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) */ if (!object || (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) { - return_VOID; + return; } /* Ensure that we have a valid object */ if (!acpi_ut_valid_internal_object(object)) { - return_VOID; + return; } ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -713,5 +737,5 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) * of all subobjects!) */ (void)acpi_ut_update_object_reference(object, REF_DECREMENT); - return_VOID; + return; } diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index a9c65fbea5f4..c3f3a7e7bdc7 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,7 +68,7 @@ ACPI_MODULE_NAME("uteval") ******************************************************************************/ acpi_status -acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, +acpi_ut_evaluate_object(struct acpi_namespace_node * prefix_node, char *path, u32 expected_return_btypes, union acpi_operand_object **return_desc) diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index 23b98945f6b7..a0ab7c02e87c 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index ed1893155f8b..ffecf4b4f0dd 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -293,11 +293,11 @@ acpi_status acpi_ut_init_globals(void) /* GPE support */ + acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_gpe_xrupt_list_head = NULL; acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; acpi_current_gpe_count = 0; - acpi_gbl_all_gpes_initialized = FALSE; acpi_gbl_global_event_handler = NULL; @@ -357,17 +357,24 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_root_node_struct.peer = NULL; acpi_gbl_root_node_struct.object = NULL; +#ifdef ACPI_DISASSEMBLER + acpi_gbl_external_list = NULL; +#endif + #ifdef ACPI_DEBUG_OUTPUT acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); #endif #ifdef ACPI_DBG_TRACK_ALLOCATIONS acpi_gbl_display_final_mem_stats = FALSE; + acpi_gbl_disable_mem_tracking = FALSE; #endif return_ACPI_STATUS(AE_OK); } +/* Public globals */ + ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index 5d84e1954575..43a170a74a61 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,10 +67,10 @@ ACPI_MODULE_NAME("utids") ******************************************************************************/ acpi_status acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id) + struct acpi_pnp_device_id **return_id) { union acpi_operand_object *obj_desc; - struct acpica_device_id *hid; + struct acpi_pnp_device_id *hid; u32 length; acpi_status status; @@ -94,16 +94,17 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, /* Allocate a buffer for the HID */ hid = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + (acpi_size) length); if (!hid) { status = AE_NO_MEMORY; goto cleanup; } - /* Area for the string starts after DEVICE_ID struct */ + /* Area for the string starts after PNP_DEVICE_ID struct */ - hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id)); + hid->string = + ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id)); /* Convert EISAID to a string or simply copy existing string */ @@ -126,6 +127,73 @@ cleanup: /******************************************************************************* * + * FUNCTION: acpi_ut_execute_SUB + * + * PARAMETERS: device_node - Node for the device + * return_id - Where the _SUB is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _SUB control method that returns the subsystem + * ID of the device. The _SUB value is always a string containing + * either a valid PNP or ACPI ID. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, + struct acpi_pnp_device_id **return_id) +{ + union acpi_operand_object *obj_desc; + struct acpi_pnp_device_id *sub; + u32 length; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_SUB); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB, + ACPI_BTYPE_STRING, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + length = obj_desc->string.length + 1; + + /* Allocate a buffer for the SUB */ + + sub = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + + (acpi_size) length); + if (!sub) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + sub->string = + ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id)); + + /* Simply copy existing string */ + + ACPI_STRCPY(sub->string, obj_desc->string.pointer); + sub->length = length; + *return_id = sub; + + cleanup: + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_UID * * PARAMETERS: device_node - Node for the device @@ -144,10 +212,10 @@ cleanup: acpi_status acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id) + struct acpi_pnp_device_id **return_id) { union acpi_operand_object *obj_desc; - struct acpica_device_id *uid; + struct acpi_pnp_device_id *uid; u32 length; acpi_status status; @@ -171,16 +239,17 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, /* Allocate a buffer for the UID */ uid = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + (acpi_size) length); if (!uid) { status = AE_NO_MEMORY; goto cleanup; } - /* Area for the string starts after DEVICE_ID struct */ + /* Area for the string starts after PNP_DEVICE_ID struct */ - uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id)); + uid->string = + ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id)); /* Convert an Integer to string, or just copy an existing string */ @@ -226,11 +295,11 @@ cleanup: acpi_status acpi_ut_execute_CID(struct acpi_namespace_node *device_node, - struct acpica_device_id_list **return_cid_list) + struct acpi_pnp_device_id_list **return_cid_list) { union acpi_operand_object **cid_objects; union acpi_operand_object *obj_desc; - struct acpica_device_id_list *cid_list; + struct acpi_pnp_device_id_list *cid_list; char *next_id_string; u32 string_area_size; u32 length; @@ -288,11 +357,12 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, /* * Now that we know the length of the CIDs, allocate return buffer: * 1) Size of the base structure + - * 2) Size of the CID DEVICE_ID array + + * 2) Size of the CID PNP_DEVICE_ID array + * 3) Size of the actual CID strings */ - cid_list_size = sizeof(struct acpica_device_id_list) + - ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size; + cid_list_size = sizeof(struct acpi_pnp_device_id_list) + + ((count - 1) * sizeof(struct acpi_pnp_device_id)) + + string_area_size; cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size); if (!cid_list) { @@ -300,10 +370,10 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, goto cleanup; } - /* Area for CID strings starts after the CID DEVICE_ID array */ + /* Area for CID strings starts after the CID PNP_DEVICE_ID array */ next_id_string = ACPI_CAST_PTR(char, cid_list->ids) + - ((acpi_size) count * sizeof(struct acpica_device_id)); + ((acpi_size) count * sizeof(struct acpi_pnp_device_id)); /* Copy/convert the CIDs to the return buffer */ diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 246798e4c938..c5d1ac44c07d 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c index b1eb7f17e110..5c26ad420344 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,11 +66,11 @@ acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock) lock->num_readers = 0; status = acpi_os_create_mutex(&lock->reader_mutex); if (ACPI_FAILURE(status)) { - return status; + return (status); } status = acpi_os_create_mutex(&lock->writer_mutex); - return status; + return (status); } void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock) @@ -108,7 +108,7 @@ acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { - return status; + return (status); } /* Acquire the write lock only for the first reader */ @@ -121,7 +121,7 @@ acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) } acpi_os_release_mutex(lock->reader_mutex); - return status; + return (status); } acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) @@ -130,7 +130,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { - return status; + return (status); } /* Release the write lock only for the very last reader */ @@ -141,7 +141,7 @@ acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) } acpi_os_release_mutex(lock->reader_mutex); - return status; + return (status); } /******************************************************************************* @@ -165,7 +165,7 @@ acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock) acpi_status status; status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER); - return status; + return (status); } void acpi_ut_release_write_lock(struct acpi_rw_lock *lock) diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index d88a8aaab2a6..909fe66e1934 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,7 +81,7 @@ typedef union uint64_overlay { * RETURN: Status (Checks for divide-by-zero) * * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) - * divide and modulo. The result is a 64-bit quotient and a + * divide and modulo. The result is a 64-bit quotient and a * 32-bit remainder. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 33c6cf7ff467..785fdd07ae56 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include <linux/module.h> - #include <acpi/acpi.h> #include "accommon.h" #include "acnamesp.h" @@ -50,36 +48,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utmisc") -#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP -/******************************************************************************* - * - * FUNCTION: ut_convert_backslashes - * - * PARAMETERS: pathname - File pathname string to be converted - * - * RETURN: Modifies the input Pathname - * - * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within - * the entire input file pathname string. - * - ******************************************************************************/ -void ut_convert_backslashes(char *pathname) -{ - - if (!pathname) { - return; - } - - while (*pathname) { - if (*pathname == '\\') { - *pathname = '/'; - } - - pathname++; - } -} -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_is_pci_root_bridge @@ -91,7 +59,6 @@ void ut_convert_backslashes(char *pathname) * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. * ******************************************************************************/ - u8 acpi_ut_is_pci_root_bridge(char *id) { @@ -138,295 +105,6 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table) /******************************************************************************* * - * FUNCTION: acpi_ut_allocate_owner_id - * - * PARAMETERS: owner_id - Where the new owner ID is returned - * - * RETURN: Status - * - * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to - * track objects created by the table or method, to be deleted - * when the method exits or the table is unloaded. - * - ******************************************************************************/ - -acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) -{ - u32 i; - u32 j; - u32 k; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_allocate_owner_id); - - /* Guard against multiple allocations of ID to the same location */ - - if (*owner_id) { - ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists", - *owner_id)); - return_ACPI_STATUS(AE_ALREADY_EXISTS); - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Find a free owner ID, cycle through all possible IDs on repeated - * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have - * to be scanned twice. - */ - for (i = 0, j = acpi_gbl_last_owner_id_index; - i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { - if (j >= ACPI_NUM_OWNERID_MASKS) { - j = 0; /* Wraparound to start of mask array */ - } - - for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { - if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { - - /* There are no free IDs in this mask */ - - break; - } - - if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { - /* - * Found a free ID. The actual ID is the bit index plus one, - * making zero an invalid Owner ID. Save this as the last ID - * allocated and update the global ID mask. - */ - acpi_gbl_owner_id_mask[j] |= (1 << k); - - acpi_gbl_last_owner_id_index = (u8) j; - acpi_gbl_next_owner_id_offset = (u8) (k + 1); - - /* - * Construct encoded ID from the index and bit position - * - * Note: Last [j].k (bit 255) is never used and is marked - * permanently allocated (prevents +1 overflow) - */ - *owner_id = - (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); - - ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Allocated OwnerId: %2.2X\n", - (unsigned int)*owner_id)); - goto exit; - } - } - - acpi_gbl_next_owner_id_offset = 0; - } - - /* - * All owner_ids have been allocated. This typically should - * not happen since the IDs are reused after deallocation. The IDs are - * allocated upon table load (one per table) and method execution, and - * they are released when a table is unloaded or a method completes - * execution. - * - * If this error happens, there may be very deep nesting of invoked control - * methods, or there may be a bug where the IDs are not released. - */ - status = AE_OWNER_ID_LIMIT; - ACPI_ERROR((AE_INFO, - "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); - - exit: - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_release_owner_id - * - * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_ID - * - * RETURN: None. No error is returned because we are either exiting a - * control method or unloading a table. Either way, we would - * ignore any error anyway. - * - * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 - * - ******************************************************************************/ - -void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) -{ - acpi_owner_id owner_id = *owner_id_ptr; - acpi_status status; - u32 index; - u32 bit; - - ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); - - /* Always clear the input owner_id (zero is an invalid ID) */ - - *owner_id_ptr = 0; - - /* Zero is not a valid owner_ID */ - - if (owner_id == 0) { - ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id)); - return_VOID; - } - - /* Mutex for the global ID mask */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* Normalize the ID to zero */ - - owner_id--; - - /* Decode ID to index/offset pair */ - - index = ACPI_DIV_32(owner_id); - bit = 1 << ACPI_MOD_32(owner_id); - - /* Free the owner ID only if it is valid */ - - if (acpi_gbl_owner_id_mask[index] & bit) { - acpi_gbl_owner_id_mask[index] ^= bit; - } else { - ACPI_ERROR((AE_INFO, - "Release of non-allocated OwnerId: 0x%2.2X", - owner_id + 1)); - } - - (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strupr (strupr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void acpi_ut_strupr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOUPPER(*string); - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_print_string - * - * PARAMETERS: string - Null terminated ASCII string - * max_length - Maximum output length - * - * RETURN: None - * - * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape - * sequences. - * - ******************************************************************************/ - -void acpi_ut_print_string(char *string, u8 max_length) -{ - u32 i; - - if (!string) { - acpi_os_printf("<\"NULL STRING PTR\">"); - return; - } - - acpi_os_printf("\""); - for (i = 0; string[i] && (i < max_length); i++) { - - /* Escape sequences */ - - switch (string[i]) { - case 0x07: - acpi_os_printf("\\a"); /* BELL */ - break; - - case 0x08: - acpi_os_printf("\\b"); /* BACKSPACE */ - break; - - case 0x0C: - acpi_os_printf("\\f"); /* FORMFEED */ - break; - - case 0x0A: - acpi_os_printf("\\n"); /* LINEFEED */ - break; - - case 0x0D: - acpi_os_printf("\\r"); /* CARRIAGE RETURN */ - break; - - case 0x09: - acpi_os_printf("\\t"); /* HORIZONTAL TAB */ - break; - - case 0x0B: - acpi_os_printf("\\v"); /* VERTICAL TAB */ - break; - - case '\'': /* Single Quote */ - case '\"': /* Double Quote */ - case '\\': /* Backslash */ - acpi_os_printf("\\%c", (int)string[i]); - break; - - default: - - /* Check for printable character or hex escape */ - - if (ACPI_IS_PRINT(string[i])) { - /* This is a normal character */ - - acpi_os_printf("%c", (int)string[i]); - } else { - /* All others will be Hex escapes */ - - acpi_os_printf("\\x%2.2X", (s32) string[i]); - } - break; - } - } - acpi_os_printf("\""); - - if (i == max_length && string[i]) { - acpi_os_printf("..."); - } -} - -/******************************************************************************* - * * FUNCTION: acpi_ut_dword_byte_swap * * PARAMETERS: value - Value to be converted @@ -469,8 +147,8 @@ u32 acpi_ut_dword_byte_swap(u32 value) * RETURN: None * * DESCRIPTION: Set the global integer bit width based upon the revision - * of the DSDT. For Revision 1 and 0, Integers are 32 bits. - * For Revision 2 and above, Integers are 64 bits. Yes, this + * of the DSDT. For Revision 1 and 0, Integers are 32 bits. + * For Revision 2 and above, Integers are 64 bits. Yes, this * makes a difference. * ******************************************************************************/ @@ -494,348 +172,6 @@ void acpi_ut_set_integer_width(u8 revision) } } -#ifdef ACPI_DEBUG_OUTPUT -/******************************************************************************* - * - * FUNCTION: acpi_ut_display_init_pathname - * - * PARAMETERS: type - Object type of the node - * obj_handle - Handle whose pathname will be displayed - * path - Additional path string to be appended. - * (NULL if no extra path) - * - * RETURN: acpi_status - * - * DESCRIPTION: Display full pathname of an object, DEBUG ONLY - * - ******************************************************************************/ - -void -acpi_ut_display_init_pathname(u8 type, - struct acpi_namespace_node *obj_handle, - char *path) -{ - acpi_status status; - struct acpi_buffer buffer; - - ACPI_FUNCTION_ENTRY(); - - /* Only print the path if the appropriate debug level is enabled */ - - if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { - return; - } - - /* Get the full pathname to the node */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname(obj_handle, &buffer); - if (ACPI_FAILURE(status)) { - return; - } - - /* Print what we're doing */ - - switch (type) { - case ACPI_TYPE_METHOD: - acpi_os_printf("Executing "); - break; - - default: - acpi_os_printf("Initializing "); - break; - } - - /* Print the object type and pathname */ - - acpi_os_printf("%-12s %s", - acpi_ut_get_type_name(type), (char *)buffer.pointer); - - /* Extra path is used to append names like _STA, _INI, etc. */ - - if (path) { - acpi_os_printf(".%s", path); - } - acpi_os_printf("\n"); - - ACPI_FREE(buffer.pointer); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_char - * - * PARAMETERS: char - The character to be examined - * position - Byte position (0-3) - * - * RETURN: TRUE if the character is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI character. Must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - * We allow a '!' as the last character because of the ASF! table - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_char(char character, u32 position) -{ - - if (!((character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9') || (character == '_'))) { - - /* Allow a '!' in the last position */ - - if (character == '!' && position == 3) { - return (TRUE); - } - - return (FALSE); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_valid_acpi_name - * - * PARAMETERS: name - The name to be examined - * - * RETURN: TRUE if the name is valid, FALSE otherwise - * - * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: - * 1) Upper case alpha - * 2) numeric - * 3) underscore - * - ******************************************************************************/ - -u8 acpi_ut_valid_acpi_name(u32 name) -{ - u32 i; - - ACPI_FUNCTION_ENTRY(); - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - if (!acpi_ut_valid_acpi_char - ((ACPI_CAST_PTR(char, &name))[i], i)) { - return (FALSE); - } - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_repair_name - * - * PARAMETERS: name - The ACPI name to be repaired - * - * RETURN: Repaired version of the name - * - * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and - * return the new name. - * - ******************************************************************************/ - -acpi_name acpi_ut_repair_name(char *name) -{ - u32 i; - char new_name[ACPI_NAME_SIZE]; - - for (i = 0; i < ACPI_NAME_SIZE; i++) { - new_name[i] = name[i]; - - /* - * Replace a bad character with something printable, yet technically - * still invalid. This prevents any collisions with existing "good" - * names in the namespace. - */ - if (!acpi_ut_valid_acpi_char(name[i], i)) { - new_name[i] = '*'; - } - } - - return (*(u32 *) new_name); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strtoul64 - * - * PARAMETERS: string - Null terminated string - * base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of to_integer' - * ret_integer - Where the converted integer is returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. - * NOTE: Does not support Octal strings, not needed. - * - ******************************************************************************/ - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer) -{ - u32 this_digit = 0; - u64 return_value = 0; - u64 quotient; - u64 dividend; - u32 to_integer_op = (base == ACPI_ANY_BASE); - u32 mode32 = (acpi_gbl_integer_byte_width == 4); - u8 valid_digits = 0; - u8 sign_of0x = 0; - u8 term = 0; - - ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); - - switch (base) { - case ACPI_ANY_BASE: - case 16: - break; - - default: - /* Invalid Base */ - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!string) { - goto error_exit; - } - - /* Skip over any white space in the buffer */ - - while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { - string++; - } - - if (to_integer_op) { - /* - * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. - * We need to determine if it is decimal or hexadecimal. - */ - if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - sign_of0x = 1; - base = 16; - - /* Skip over the leading '0x' */ - string += 2; - } else { - base = 10; - } - } - - /* Any string left? Check that '0x' is not followed by white space. */ - - if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { - if (to_integer_op) { - goto error_exit; - } else { - goto all_done; - } - } - - /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter - */ - dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - - /* Main loop: convert the string to a 32- or 64-bit integer */ - - while (*string) { - if (ACPI_IS_DIGIT(*string)) { - - /* Convert ASCII 0-9 to Decimal value */ - - this_digit = ((u8) * string) - '0'; - } else if (base == 10) { - - /* Digit is out of range; possible in to_integer case only */ - - term = 1; - } else { - this_digit = (u8) ACPI_TOUPPER(*string); - if (ACPI_IS_XDIGIT((char)this_digit)) { - - /* Convert ASCII Hex char to value */ - - this_digit = this_digit - 'A' + 10; - } else { - term = 1; - } - } - - if (term) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } else if ((valid_digits == 0) && (this_digit == 0) - && !sign_of0x) { - - /* Skip zeros */ - string++; - continue; - } - - valid_digits++; - - if (sign_of0x && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { - /* - * This is to_integer operation case. - * No any restrictions for string-to-integer conversion, - * see ACPI spec. - */ - goto error_exit; - } - - /* Divide the digit into the correct position */ - - (void)acpi_ut_short_divide((dividend - (u64) this_digit), - base, "ient, NULL); - - if (return_value > quotient) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } - - return_value *= base; - return_value += this_digit; - string++; - } - - /* All done, normal exit */ - - all_done: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(return_value))); - - *ret_integer = return_value; - return_ACPI_STATUS(AE_OK); - - error_exit: - /* Base was set/validated above */ - - if (base == 10) { - return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); - } else { - return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); - } -} - /******************************************************************************* * * FUNCTION: acpi_ut_create_update_state_and_push @@ -890,7 +226,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object, ******************************************************************************/ acpi_status -acpi_ut_walk_package_tree(union acpi_operand_object * source_object, +acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void *target_object, acpi_pkg_callback walk_callback, void *context) { @@ -917,10 +253,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, /* * Check for: - * 1) An uninitialized package element. It is completely + * 1) An uninitialized package element. It is completely * legal to declare a package and leave it uninitialized * 2) Not an internal object - can be a namespace node instead - * 3) Any type other than a package. Packages are handled in else + * 3) Any type other than a package. Packages are handled in else * case below. */ if ((!this_source_obj) || @@ -939,7 +275,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, state->pkg.source_object->package.count) { /* * We've handled all of the objects at this level, This means - * that we have just completed a package. That package may + * that we have just completed a package. That package may * have contained one or more packages itself. * * Delete this state and pop the previous state (package). @@ -1001,3 +337,71 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, return_ACPI_STATUS(AE_AML_INTERNAL); } + +#ifdef ACPI_DEBUG_OUTPUT +/******************************************************************************* + * + * FUNCTION: acpi_ut_display_init_pathname + * + * PARAMETERS: type - Object type of the node + * obj_handle - Handle whose pathname will be displayed + * path - Additional path string to be appended. + * (NULL if no extra path) + * + * RETURN: acpi_status + * + * DESCRIPTION: Display full pathname of an object, DEBUG ONLY + * + ******************************************************************************/ + +void +acpi_ut_display_init_pathname(u8 type, + struct acpi_namespace_node *obj_handle, + char *path) +{ + acpi_status status; + struct acpi_buffer buffer; + + ACPI_FUNCTION_ENTRY(); + + /* Only print the path if the appropriate debug level is enabled */ + + if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { + return; + } + + /* Get the full pathname to the node */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer); + if (ACPI_FAILURE(status)) { + return; + } + + /* Print what we're doing */ + + switch (type) { + case ACPI_TYPE_METHOD: + acpi_os_printf("Executing "); + break; + + default: + acpi_os_printf("Initializing "); + break; + } + + /* Print the object type and pathname */ + + acpi_os_printf("%-12s %s", + acpi_ut_get_type_name(type), (char *)buffer.pointer); + + /* Extra path is used to append names like _STA, _INI, etc. */ + + if (path) { + acpi_os_printf(".%s", path); + } + acpi_os_printf("\n"); + + ACPI_FREE(buffer.pointer); +} +#endif diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 296baa676bc5..22feb99b8e35 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -193,6 +193,8 @@ static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) acpi_gbl_mutex_info[mutex_id].mutex = NULL; acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + + return_VOID; } /******************************************************************************* @@ -226,9 +228,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) /* * Mutex debug code, for internal debugging only. * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than or equal to this one. If so, the thread has violated - * the mutex ordering rule. This indicates a coding error somewhere in + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { @@ -319,9 +321,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) /* * Mutex debug code, for internal debugging only. * - * Deadlock prevention. Check if this thread owns any mutexes of value - * greater than this one. If so, the thread has violated the mutex - * ordering rule. This indicates a coding error somewhere in + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) { diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index 655f0799a391..1099f5c069f8 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,7 +77,7 @@ acpi_ut_get_element_length(u8 object_type, * * NOTE: We always allocate the worst-case object descriptor because * these objects are cached, and we want them to be - * one-size-satisifies-any-request. This in itself may not be + * one-size-satisifies-any-request. This in itself may not be * the most memory efficient, but the efficiency of the object * cache should more than make up for this! * @@ -370,9 +370,9 @@ u8 acpi_ut_valid_internal_object(void *object) * line_number - Caller's line number (for error output) * component_id - Caller's component ID (for error output) * - * RETURN: Pointer to newly allocated object descriptor. Null on error + * RETURN: Pointer to newly allocated object descriptor. Null on error * - * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle * error conditions. * ******************************************************************************/ @@ -419,7 +419,7 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object) { ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); - /* Object must be a union acpi_operand_object */ + /* Object must be of type union acpi_operand_object */ if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { ACPI_ERROR((AE_INFO, @@ -554,7 +554,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, /* * Account for the space required by the object rounded up to the next - * multiple of the machine word size. This keeps each object aligned + * multiple of the machine word size. This keeps each object aligned * on a machine word boundary. (preventing alignment faults on some * machines.) */ diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 676285d6116d..36a7d361d7cb 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c new file mode 100644 index 000000000000..835340b26d37 --- /dev/null +++ b/drivers/acpi/acpica/utownerid.c @@ -0,0 +1,218 @@ +/******************************************************************************* + * + * Module Name: utownerid - Support for Table/Method Owner IDs + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utownerid") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_owner_id + * + * PARAMETERS: owner_id - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ +acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) +{ + u32 i; + u32 j; + u32 k; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_allocate_owner_id); + + /* Guard against multiple allocations of ID to the same location */ + + if (*owner_id) { + ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists", + *owner_id)); + return_ACPI_STATUS(AE_ALREADY_EXISTS); + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = acpi_gbl_last_owner_id_index; + i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) { + if (j >= ACPI_NUM_OWNERID_MASKS) { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { + if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + + /* There are no free IDs in this mask */ + + break; + } + + if (!(acpi_gbl_owner_id_mask[j] & (1 << k))) { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + acpi_gbl_owner_id_mask[j] |= (1 << k); + + acpi_gbl_last_owner_id_index = (u8)j; + acpi_gbl_next_owner_id_offset = (u8)(k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *owner_id = + (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); + + ACPI_DEBUG_PRINT((ACPI_DB_VALUES, + "Allocated OwnerId: %2.2X\n", + (unsigned int)*owner_id)); + goto exit; + } + } + + acpi_gbl_next_owner_id_offset = 0; + } + + /* + * All owner_ids have been allocated. This typically should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. + */ + status = AE_OWNER_ID_LIMIT; + ACPI_ERROR((AE_INFO, + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); + + exit: + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_release_owner_id + * + * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_ID + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 + * + ******************************************************************************/ + +void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) +{ + acpi_owner_id owner_id = *owner_id_ptr; + acpi_status status; + u32 index; + u32 bit; + + ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); + + /* Always clear the input owner_id (zero is an invalid ID) */ + + *owner_id_ptr = 0; + + /* Zero is not a valid owner_ID */ + + if (owner_id == 0) { + ACPI_ERROR((AE_INFO, "Invalid OwnerId: 0x%2.2X", owner_id)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); + if (ACPI_FAILURE(status)) { + return_VOID; + } + + /* Normalize the ID to zero */ + + owner_id--; + + /* Decode ID to index/offset pair */ + + index = ACPI_DIV_32(owner_id); + bit = 1 << ACPI_MOD_32(owner_id); + + /* Free the owner ID only if it is valid */ + + if (acpi_gbl_owner_id_mask[index] & bit) { + acpi_gbl_owner_id_mask[index] ^= bit; + } else { + ACPI_ERROR((AE_INFO, + "Release of non-allocated OwnerId: 0x%2.2X", + owner_id + 1)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); + return_VOID; +} diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index e38bef4980bc..cb7fa491decf 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -127,7 +127,9 @@ const char *acpi_gbl_rw_decode[] = { const char *acpi_gbl_shr_decode[] = { "Exclusive", - "Shared" + "Shared", + "ExclusiveAndWake", /* ACPI 5.0 */ + "SharedAndWake" /* ACPI 5.0 */ }; const char *acpi_gbl_siz_decode[] = { @@ -383,26 +385,16 @@ static const u8 acpi_gbl_resource_types[] = { ACPI_VARIABLE_LENGTH /* 0E *serial_bus */ }; -/* - * For the iASL compiler/disassembler, we don't want any error messages - * because the disassembler uses the resource validation code to determine - * if Buffer objects are actually Resource Templates. - */ -#ifdef ACPI_ASL_COMPILER -#define ACPI_RESOURCE_ERROR(plist) -#else -#define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist) -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_walk_aml_resources * - * PARAMETERS: aml - Pointer to the raw AML resource template - * aml_length - Length of the entire template - * user_function - Called once for each descriptor found. If - * NULL, a pointer to the end_tag is returned - * context - Passed to user_function + * PARAMETERS: walk_state - Current walk info + * PARAMETERS: aml - Pointer to the raw AML resource template + * aml_length - Length of the entire template + * user_function - Called once for each descriptor found. If + * NULL, a pointer to the end_tag is returned + * context - Passed to user_function * * RETURN: Status * @@ -412,7 +404,8 @@ static const u8 acpi_gbl_resource_types[] = { ******************************************************************************/ acpi_status -acpi_ut_walk_aml_resources(u8 * aml, +acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, + u8 *aml, acpi_size aml_length, acpi_walk_aml_callback user_function, void **context) { @@ -441,7 +434,8 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Validate the Resource Type and Resource Length */ - status = acpi_ut_validate_resource(aml, &resource_index); + status = + acpi_ut_validate_resource(walk_state, aml, &resource_index); if (ACPI_FAILURE(status)) { /* * Exit on failure. Cannot continue because the descriptor length @@ -498,7 +492,8 @@ acpi_ut_walk_aml_resources(u8 * aml, /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */ - (void)acpi_ut_validate_resource(end_tag, &resource_index); + (void)acpi_ut_validate_resource(walk_state, end_tag, + &resource_index); status = user_function(end_tag, 2, offset, resource_index, context); if (ACPI_FAILURE(status)) { @@ -513,9 +508,10 @@ acpi_ut_walk_aml_resources(u8 * aml, * * FUNCTION: acpi_ut_validate_resource * - * PARAMETERS: aml - Pointer to the raw AML resource descriptor - * return_index - Where the resource index is returned. NULL - * if the index is not required. + * PARAMETERS: walk_state - Current walk info + * aml - Pointer to the raw AML resource descriptor + * return_index - Where the resource index is returned. NULL + * if the index is not required. * * RETURN: Status, and optionally the Index into the global resource tables * @@ -525,7 +521,9 @@ acpi_ut_walk_aml_resources(u8 * aml, * ******************************************************************************/ -acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) +acpi_status +acpi_ut_validate_resource(struct acpi_walk_state *walk_state, + void *aml, u8 *return_index) { union aml_resource *aml_resource; u8 resource_type; @@ -627,10 +625,12 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) if ((aml_resource->common_serial_bus.type == 0) || (aml_resource->common_serial_bus.type > AML_RESOURCE_MAX_SERIALBUSTYPE)) { - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", - aml_resource->common_serial_bus. - type)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", + aml_resource->common_serial_bus. + type)); + } return (AE_AML_INVALID_RESOURCE_TYPE); } } @@ -645,18 +645,22 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) invalid_resource: - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid/unsupported resource descriptor: Type 0x%2.2X", - resource_type)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + resource_type)); + } return (AE_AML_INVALID_RESOURCE_TYPE); bad_resource_length: - ACPI_RESOURCE_ERROR((AE_INFO, - "Invalid resource descriptor length: Type " - "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", - resource_type, resource_length, - minimum_resource_length)); + if (walk_state) { + ACPI_ERROR((AE_INFO, + "Invalid resource descriptor length: Type " + "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", + resource_type, resource_length, + minimum_resource_length)); + } return (AE_AML_BAD_RESOURCE_LENGTH); } @@ -800,8 +804,7 @@ u32 acpi_ut_get_descriptor_length(void *aml) ******************************************************************************/ acpi_status -acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, - u8 ** end_tag) +acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag) { acpi_status status; @@ -816,7 +819,7 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, /* Validate the template and get a pointer to the end_tag */ - status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, + status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer, obj_desc->buffer.length, NULL, (void **)end_tag); diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index a1c988260073..a6b729d4c1dc 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,14 +97,13 @@ void acpi_ut_push_generic_state(union acpi_generic_state **list_head, union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE(ut_push_generic_state); + ACPI_FUNCTION_ENTRY(); /* Push the state object onto the front of the list (stack) */ state->common.next = *list_head; *list_head = state; - - return_VOID; + return; } /******************************************************************************* @@ -124,7 +123,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_pop_generic_state); + ACPI_FUNCTION_ENTRY(); /* Remove the state object at the head of the list (stack) */ @@ -136,7 +135,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state *list_head = state->common.next; } - return_PTR(state); + return (state); } /******************************************************************************* @@ -147,7 +146,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state * * RETURN: The new state object. NULL on failure. * - * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * DESCRIPTION: Create a generic state object. Attempt to obtain one from * the global state cache; If none available, create a new one. * ******************************************************************************/ @@ -186,13 +185,13 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_create_thread_state); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -207,7 +206,7 @@ struct acpi_thread_state *acpi_ut_create_thread_state(void) state->thread.thread_id = (acpi_thread_id) 1; } - return_PTR((struct acpi_thread_state *)state); + return ((struct acpi_thread_state *)state); } /******************************************************************************* @@ -230,13 +229,13 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -244,8 +243,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; state->update.object = object; state->update.value = action; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -267,13 +265,13 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the update struct */ @@ -283,8 +281,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, state->pkg.dest_object = external_object; state->pkg.index = index; state->pkg.num_packages = 1; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -304,21 +301,20 @@ union acpi_generic_state *acpi_ut_create_control_state(void) { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE(ut_create_control_state); + ACPI_FUNCTION_ENTRY(); /* Create the generic state object */ state = acpi_ut_create_generic_state(); if (!state) { - return_PTR(NULL); + return (NULL); } /* Init fields specific to the control struct */ state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; - - return_PTR(state); + return (state); } /******************************************************************************* @@ -336,12 +332,12 @@ union acpi_generic_state *acpi_ut_create_control_state(void) void acpi_ut_delete_generic_state(union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE(ut_delete_generic_state); + ACPI_FUNCTION_ENTRY(); /* Ignore null state */ if (state) { (void)acpi_os_release_object(acpi_gbl_state_cache, state); } - return_VOID; + return; } diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c new file mode 100644 index 000000000000..b3e36a81aa4d --- /dev/null +++ b/drivers/acpi/acpica/utstring.c @@ -0,0 +1,574 @@ +/******************************************************************************* + * + * Module Name: utstring - Common functions for strings and characters + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utstring") + +/* + * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit + * version of strtoul. + */ +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: acpi_ut_strlwr (strlwr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to lowercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ +void acpi_ut_strlwr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOLOWER(*string); + } + + return; +} + +/****************************************************************************** + * + * FUNCTION: acpi_ut_stricmp (stricmp) + * + * PARAMETERS: string1 - first string to compare + * string2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare + * strings with no case sensitivity) + * + ******************************************************************************/ + +int acpi_ut_stricmp(char *string1, char *string2) +{ + int c1; + int c2; + + do { + c1 = tolower((int)*string1); + c2 = tolower((int)*string2); + + string1++; + string2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strupr (strupr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void acpi_ut_strupr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)ACPI_TOUPPER(*string); + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul64 + * + * PARAMETERS: string - Null terminated string + * base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' + * ret_integer - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) +{ + u32 this_digit = 0; + u64 return_value = 0; + u64 quotient; + u64 dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; + + ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); + + switch (base) { + case ACPI_ANY_BASE: + case 16: + break; + + default: + /* Invalid Base */ + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!string) { + goto error_exit; + } + + /* Skip over any white space in the buffer */ + + while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { + string++; + } + + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { + sign_of0x = 1; + base = 16; + + /* Skip over the leading '0x' */ + string += 2; + } else { + base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*string) { + if (ACPI_IS_DIGIT(*string)) { + + /* Convert ASCII 0-9 to Decimal value */ + + this_digit = ((u8)*string) - '0'; + } else if (base == 10) { + + /* Digit is out of range; possible in to_integer case only */ + + term = 1; + } else { + this_digit = (u8)ACPI_TOUPPER(*string); + if (ACPI_IS_XDIGIT((char)this_digit)) { + + /* Convert ASCII Hex char to value */ + + this_digit = this_digit - 'A' + 10; + } else { + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; + } + + /* Divide the digit into the correct position */ + + (void)acpi_ut_short_divide((dividend - (u64)this_digit), + base, "ient, NULL); + + if (return_value > quotient) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } + + return_value *= base; + return_value += this_digit; + string++; + } + + /* All done, normal exit */ + + all_done: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(return_value))); + + *ret_integer = return_value; + return_ACPI_STATUS(AE_OK); + + error_exit: + /* Base was set/validated above */ + + if (base == 10) { + return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); + } else { + return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_print_string + * + * PARAMETERS: string - Null terminated ASCII string + * max_length - Maximum output length + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void acpi_ut_print_string(char *string, u8 max_length) +{ + u32 i; + + if (!string) { + acpi_os_printf("<\"NULL STRING PTR\">"); + return; + } + + acpi_os_printf("\""); + for (i = 0; string[i] && (i < max_length); i++) { + + /* Escape sequences */ + + switch (string[i]) { + case 0x07: + acpi_os_printf("\\a"); /* BELL */ + break; + + case 0x08: + acpi_os_printf("\\b"); /* BACKSPACE */ + break; + + case 0x0C: + acpi_os_printf("\\f"); /* FORMFEED */ + break; + + case 0x0A: + acpi_os_printf("\\n"); /* LINEFEED */ + break; + + case 0x0D: + acpi_os_printf("\\r"); /* CARRIAGE RETURN */ + break; + + case 0x09: + acpi_os_printf("\\t"); /* HORIZONTAL TAB */ + break; + + case 0x0B: + acpi_os_printf("\\v"); /* VERTICAL TAB */ + break; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + acpi_os_printf("\\%c", (int)string[i]); + break; + + default: + + /* Check for printable character or hex escape */ + + if (ACPI_IS_PRINT(string[i])) { + /* This is a normal character */ + + acpi_os_printf("%c", (int)string[i]); + } else { + /* All others will be Hex escapes */ + + acpi_os_printf("\\x%2.2X", (s32) string[i]); + } + break; + } + } + acpi_os_printf("\""); + + if (i == max_length && string[i]) { + acpi_os_printf("..."); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_char + * + * PARAMETERS: char - The character to be examined + * position - Byte position (0-3) + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_char(char character, u32 position) +{ + + if (!((character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || (character == '_'))) { + + /* Allow a '!' in the last position */ + + if (character == '!' && position == 3) { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_valid_acpi_name + * + * PARAMETERS: name - The name to be examined + * + * RETURN: TRUE if the name is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_name(u32 name) +{ + u32 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!acpi_ut_valid_acpi_char + ((ACPI_CAST_PTR(char, &name))[i], i)) { + return (FALSE); + } + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_repair_name + * + * PARAMETERS: name - The ACPI name to be repaired + * + * RETURN: Repaired version of the name + * + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. NOTE: the Name parameter must reside in + * read/write memory, cannot be a const. + * + * An ACPI Name must consist of valid ACPI characters. We will repair the name + * if necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + * + ******************************************************************************/ + +void acpi_ut_repair_name(char *name) +{ + u32 i; + u8 found_bad_char = FALSE; + u32 original_name; + + ACPI_FUNCTION_NAME(ut_repair_name); + + ACPI_MOVE_NAME(&original_name, name); + + /* Check each character in the name */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (acpi_ut_valid_acpi_char(name[i], i)) { + continue; + } + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + name[i] = '*'; + found_bad_char = TRUE; + } + + if (found_bad_char) { + + /* Report warning only if in strict mode or debug mode */ + + if (!acpi_gbl_enable_interpreter_slack) { + ACPI_WARNING((AE_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + original_name, name)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + original_name, name)); + } + } +} + +#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP +/******************************************************************************* + * + * FUNCTION: ut_convert_backslashes + * + * PARAMETERS: pathname - File pathname string to be converted + * + * RETURN: Modifies the input Pathname + * + * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within + * the entire input file pathname string. + * + ******************************************************************************/ + +void ut_convert_backslashes(char *pathname) +{ + + if (!pathname) { + return; + } + + while (*pathname) { + if (*pathname == '\\') { + *pathname = '/'; + } + + pathname++; + } +} +#endif diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c new file mode 100644 index 000000000000..62774c7b76a8 --- /dev/null +++ b/drivers/acpi/acpica/uttrack.c @@ -0,0 +1,692 @@ +/****************************************************************************** + * + * Module Name: uttrack - Memory allocation tracking routines (debug only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * These procedures are used for tracking memory leaks in the subsystem, and + * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. + * + * Each memory allocation is tracked via a doubly linked list. Each + * element contains the caller's component, module name, function name, and + * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call + * acpi_ut_track_allocation to add an element to the list; deletion + * occurs in the body of acpi_ut_free. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("uttrack") + +/* Local prototypes */ +static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct + acpi_debug_mem_block + *allocation); + +static acpi_status +acpi_ut_track_allocation(struct acpi_debug_mem_block *address, + acpi_size size, + u8 alloc_type, + u32 component, const char *module, u32 line); + +static acpi_status +acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, + u32 component, const char *module, u32 line); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_list + * + * PARAMETERS: cache_name - Ascii name for the cache + * object_size - Size of each cached object + * return_cache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a local memory list for tracking purposed + * + ******************************************************************************/ + +acpi_status +acpi_ut_create_list(char *list_name, + u16 object_size, struct acpi_memory_list **return_cache) +{ + struct acpi_memory_list *cache; + + cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); + if (!cache) { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); + + cache->list_name = list_name; + cache->object_size = object_size; + + *return_cache = cache; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_and_track + * + * PARAMETERS: size - Size of the allocation + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ******************************************************************************/ + +void *acpi_ut_allocate_and_track(acpi_size size, + u32 component, const char *module, u32 line) +{ + struct acpi_debug_mem_block *allocation; + acpi_status status; + + allocation = + acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header), + component, module, line); + if (!allocation) { + return (NULL); + } + + status = acpi_ut_track_allocation(allocation, size, + ACPI_MEM_MALLOC, component, module, + line); + if (ACPI_FAILURE(status)) { + acpi_os_free(allocation); + return (NULL); + } + + acpi_gbl_global_list->total_allocated++; + acpi_gbl_global_list->total_size += (u32)size; + acpi_gbl_global_list->current_total_size += (u32)size; + if (acpi_gbl_global_list->current_total_size > + acpi_gbl_global_list->max_occupied) { + acpi_gbl_global_list->max_occupied = + acpi_gbl_global_list->current_total_size; + } + + return ((void *)&allocation->user_space); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_allocate_zeroed_and_track + * + * PARAMETERS: size - Size of the allocation + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ******************************************************************************/ + +void *acpi_ut_allocate_zeroed_and_track(acpi_size size, + u32 component, + const char *module, u32 line) +{ + struct acpi_debug_mem_block *allocation; + acpi_status status; + + allocation = + acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header), + component, module, line); + if (!allocation) { + + /* Report allocation error */ + + ACPI_ERROR((module, line, + "Could not allocate size %u", (u32)size)); + return (NULL); + } + + status = acpi_ut_track_allocation(allocation, size, + ACPI_MEM_CALLOC, component, module, + line); + if (ACPI_FAILURE(status)) { + acpi_os_free(allocation); + return (NULL); + } + + acpi_gbl_global_list->total_allocated++; + acpi_gbl_global_list->total_size += (u32)size; + acpi_gbl_global_list->current_total_size += (u32)size; + if (acpi_gbl_global_list->current_total_size > + acpi_gbl_global_list->max_occupied) { + acpi_gbl_global_list->max_occupied = + acpi_gbl_global_list->current_total_size; + } + + return ((void *)&allocation->user_space); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_free_and_track + * + * PARAMETERS: allocation - Address of the memory to deallocate + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Allocation + * + ******************************************************************************/ + +void +acpi_ut_free_and_track(void *allocation, + u32 component, const char *module, u32 line) +{ + struct acpi_debug_mem_block *debug_block; + acpi_status status; + + ACPI_FUNCTION_TRACE_PTR(ut_free, allocation); + + if (NULL == allocation) { + ACPI_ERROR((module, line, "Attempt to delete a NULL address")); + + return_VOID; + } + + debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block, + (((char *)allocation) - + sizeof(struct acpi_debug_mem_header))); + + acpi_gbl_global_list->total_freed++; + acpi_gbl_global_list->current_total_size -= debug_block->size; + + status = acpi_ut_remove_allocation(debug_block, + component, module, line); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Could not free memory")); + } + + acpi_os_free(debug_block); + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_find_allocation + * + * PARAMETERS: allocation - Address of allocated memory + * + * RETURN: Three cases: + * 1) List is empty, NULL is returned. + * 2) Element was found. Returns Allocation parameter. + * 3) Element was not found. Returns position where it should be + * inserted into the list. + * + * DESCRIPTION: Searches for an element in the global allocation tracking list. + * If the element is not found, returns the location within the + * list where the element should be inserted. + * + * Note: The list is ordered by larger-to-smaller addresses. + * + * This global list is used to detect memory leaks in ACPICA as + * well as other issues such as an attempt to release the same + * internal object more than once. Although expensive as far + * as cpu time, this list is much more helpful for finding these + * types of issues than using memory leak detectors outside of + * the ACPICA code. + * + ******************************************************************************/ + +static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct + acpi_debug_mem_block + *allocation) +{ + struct acpi_debug_mem_block *element; + + element = acpi_gbl_global_list->list_head; + if (!element) { + return (NULL); + } + + /* + * Search for the address. + * + * Note: List is ordered by larger-to-smaller addresses, on the + * assumption that a new allocation usually has a larger address + * than previous allocations. + */ + while (element > allocation) { + + /* Check for end-of-list */ + + if (!element->next) { + return (element); + } + + element = element->next; + } + + if (element == allocation) { + return (element); + } + + return (element->previous); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_track_allocation + * + * PARAMETERS: allocation - Address of allocated memory + * size - Size of the allocation + * alloc_type - MEM_MALLOC or MEM_CALLOC + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Status + * + * DESCRIPTION: Inserts an element into the global allocation tracking list. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, + acpi_size size, + u8 alloc_type, + u32 component, const char *module, u32 line) +{ + struct acpi_memory_list *mem_list; + struct acpi_debug_mem_block *element; + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation); + + if (acpi_gbl_disable_mem_tracking) { + return_ACPI_STATUS(AE_OK); + } + + mem_list = acpi_gbl_global_list; + status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Search the global list for this address to make sure it is not + * already present. This will catch several kinds of problems. + */ + element = acpi_ut_find_allocation(allocation); + if (element == allocation) { + ACPI_ERROR((AE_INFO, + "UtTrackAllocation: Allocation (%p) already present in global list!", + allocation)); + goto unlock_and_exit; + } + + /* Fill in the instance data */ + + allocation->size = (u32)size; + allocation->alloc_type = alloc_type; + allocation->component = component; + allocation->line = line; + + ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); + allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; + + if (!element) { + + /* Insert at list head */ + + if (mem_list->list_head) { + ((struct acpi_debug_mem_block *)(mem_list->list_head))-> + previous = allocation; + } + + allocation->next = mem_list->list_head; + allocation->previous = NULL; + + mem_list->list_head = allocation; + } else { + /* Insert after element */ + + allocation->next = element->next; + allocation->previous = element; + + if (element->next) { + (element->next)->previous = allocation; + } + + element->next = allocation; + } + + unlock_and_exit: + status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_remove_allocation + * + * PARAMETERS: allocation - Address of allocated memory + * component - Component type of caller + * module - Source file name of caller + * line - Line number of caller + * + * RETURN: Status + * + * DESCRIPTION: Deletes an element from the global allocation tracking list. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, + u32 component, const char *module, u32 line) +{ + struct acpi_memory_list *mem_list; + acpi_status status; + + ACPI_FUNCTION_NAME(ut_remove_allocation); + + if (acpi_gbl_disable_mem_tracking) { + return (AE_OK); + } + + mem_list = acpi_gbl_global_list; + if (NULL == mem_list->list_head) { + + /* No allocations! */ + + ACPI_ERROR((module, line, + "Empty allocation list, nothing to free!")); + + return (AE_OK); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Unlink */ + + if (allocation->previous) { + (allocation->previous)->next = allocation->next; + } else { + mem_list->list_head = allocation->next; + } + + if (allocation->next) { + (allocation->next)->previous = allocation->previous; + } + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", + &allocation->user_space, allocation->size)); + + /* Mark the segment as deleted */ + + ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size); + + status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_allocation_info + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Print some info about the outstanding allocations. + * + ******************************************************************************/ + +void acpi_ut_dump_allocation_info(void) +{ +/* + struct acpi_memory_list *mem_list; +*/ + + ACPI_FUNCTION_TRACE(ut_dump_allocation_info); + +/* + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current allocations", + mem_list->current_count, + ROUND_UP_TO_1K (mem_list->current_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", + mem_list->max_concurrent_count, + ROUND_UP_TO_1K (mem_list->max_concurrent_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", + running_object_count, + ROUND_UP_TO_1K (running_object_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", + running_alloc_count, + ROUND_UP_TO_1K (running_alloc_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current Nodes", + acpi_gbl_current_node_count, + ROUND_UP_TO_1K (acpi_gbl_current_node_size))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max Nodes", + acpi_gbl_max_concurrent_node_count, + ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * + sizeof (struct acpi_namespace_node))))); +*/ + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_allocations + * + * PARAMETERS: component - Component(s) to dump info for. + * module - Module to dump info for. NULL means all. + * + * RETURN: None + * + * DESCRIPTION: Print a list of all outstanding allocations. + * + ******************************************************************************/ + +void acpi_ut_dump_allocations(u32 component, const char *module) +{ + struct acpi_debug_mem_block *element; + union acpi_descriptor *descriptor; + u32 num_outstanding = 0; + u8 descriptor_type; + + ACPI_FUNCTION_TRACE(ut_dump_allocations); + + if (acpi_gbl_disable_mem_tracking) { + return_VOID; + } + + /* + * Walk the allocation list. + */ + if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) { + return_VOID; + } + + element = acpi_gbl_global_list->list_head; + while (element) { + if ((element->component & component) && + ((module == NULL) + || (0 == ACPI_STRCMP(module, element->module)))) { + descriptor = + ACPI_CAST_PTR(union acpi_descriptor, + &element->user_space); + + if (element->size < + sizeof(struct acpi_common_descriptor)) { + acpi_os_printf("%p Length 0x%04X %9.9s-%u " + "[Not a Descriptor - too small]\n", + descriptor, element->size, + element->module, element->line); + } else { + /* Ignore allocated objects that are in a cache */ + + if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) != + ACPI_DESC_TYPE_CACHED) { + acpi_os_printf + ("%p Length 0x%04X %9.9s-%u [%s] ", + descriptor, element->size, + element->module, element->line, + acpi_ut_get_descriptor_name + (descriptor)); + + /* Validate the descriptor type using Type field and length */ + + descriptor_type = 0; /* Not a valid descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE + (descriptor)) { + case ACPI_DESC_TYPE_OPERAND: + if (element->size == + sizeof(union + acpi_operand_object)) + { + descriptor_type = + ACPI_DESC_TYPE_OPERAND; + } + break; + + case ACPI_DESC_TYPE_PARSER: + if (element->size == + sizeof(union + acpi_parse_object)) { + descriptor_type = + ACPI_DESC_TYPE_PARSER; + } + break; + + case ACPI_DESC_TYPE_NAMED: + if (element->size == + sizeof(struct + acpi_namespace_node)) + { + descriptor_type = + ACPI_DESC_TYPE_NAMED; + } + break; + + default: + break; + } + + /* Display additional info for the major descriptor types */ + + switch (descriptor_type) { + case ACPI_DESC_TYPE_OPERAND: + acpi_os_printf + ("%12.12s RefCount 0x%04X\n", + acpi_ut_get_type_name + (descriptor->object.common. + type), + descriptor->object.common. + reference_count); + break; + + case ACPI_DESC_TYPE_PARSER: + acpi_os_printf + ("AmlOpcode 0x%04hX\n", + descriptor->op.asl. + aml_opcode); + break; + + case ACPI_DESC_TYPE_NAMED: + acpi_os_printf("%4.4s\n", + acpi_ut_get_node_name + (&descriptor-> + node)); + break; + + default: + acpi_os_printf("\n"); + break; + } + } + } + + num_outstanding++; + } + + element = element->next; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY); + + /* Print summary */ + + if (!num_outstanding) { + ACPI_INFO((AE_INFO, "No outstanding allocations")); + } else { + ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations", + num_outstanding, num_outstanding)); + } + + return_VOID; +} + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index b09632b4f5b3..48efb446258c 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,11 +44,7 @@ #include <linux/export.h> #include <acpi/acpi.h> #include "accommon.h" -#include "acevents.h" -#include "acnamesp.h" #include "acdebug.h" -#include "actables.h" -#include "acinterp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxface") @@ -147,7 +143,7 @@ ACPI_EXPORT_SYMBOL(acpi_subsystem_status) * RETURN: status - the status of the call * * DESCRIPTION: This function is called to get information about the current - * state of the ACPI subsystem. It will return system information + * state of the ACPI subsystem. It will return system information * in the out_buffer. * * If the function fails an appropriate status will be returned @@ -238,7 +234,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) } acpi_gbl_init_handler = handler; - return AE_OK; + return (AE_OK); } ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) @@ -263,6 +259,7 @@ acpi_status acpi_purge_cached_objects(void) (void)acpi_os_purge_cache(acpi_gbl_operand_cache); (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache); (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 6d63cc39b9ae..976b6c734fce 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -297,9 +297,9 @@ ACPI_EXPORT_SYMBOL(acpi_bios_warning) * * PARAMETERS: module_name - Caller's module name (for error output) * line_number - Caller's line number (for error output) - * Pathname - Full pathname to the node + * pathname - Full pathname to the node * node_flags - From Namespace node for the method/object - * Format - Printf format string + additional args + * format - Printf format string + additional args * * RETURN: None * @@ -408,7 +408,7 @@ acpi_ut_namespace_error(const char *module_name, ACPI_MOVE_32_TO_32(&bad_name, ACPI_CAST_PTR(u32, internal_name)); - acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); + acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name); } else { /* Convert path to external format */ diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 14f523627a5e..41ebaaf8bb1a 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c index 0a40a851b354..312299721ba1 100644 --- a/drivers/acpi/acpica/utxfmutex.c +++ b/drivers/acpi/acpica/utxfmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2012, Intel Corp. + * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 00a783661d0b..46f80e2c92f7 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && *access_bit_width < 32) *access_bit_width = 32; + else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 && + *access_bit_width < 64) + *access_bit_width = 64; if ((bit_width + bit_offset) > *access_bit_width) { pr_warning(FW_BUG APEI_PFX diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index e6defd86b424..1e5d8a40101e 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -29,6 +29,7 @@ #include <linux/time.h> #include <linux/cper.h> #include <linux/acpi.h> +#include <linux/pci.h> #include <linux/aer.h> /* @@ -249,6 +250,10 @@ static const char *cper_pcie_port_type_strs[] = { static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, const struct acpi_hest_generic_data *gdata) { +#ifdef CONFIG_ACPI_APEI_PCIEAER + struct pci_dev *dev; +#endif + if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? @@ -281,10 +286,18 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", pfx, pcie->bridge.secondary_status, pcie->bridge.control); #ifdef CONFIG_ACPI_APEI_PCIEAER - if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) { - struct aer_capability_regs *aer_regs = (void *)pcie->aer_info; - cper_print_aer(pfx, gdata->error_severity, aer_regs); + dev = pci_get_domain_bus_and_slot(pcie->device_id.segment, + pcie->device_id.bus, pcie->device_id.function); + if (!dev) { + pr_err("PCI AER Cannot get PCI device %04x:%02x:%02x.%d\n", + pcie->device_id.segment, pcie->device_id.bus, + pcie->device_id.slot, pcie->device_id.function); + return; } + if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) + cper_print_aer(pfx, dev, gdata->error_severity, + (struct aer_capability_regs *) pcie->aer_info); + pci_dev_put(dev); #endif } diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 8e1793649ec0..8d457b55c55a 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -367,7 +367,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, * This will cause resource conflict with regular memory. So * remove it from trigger table resources. */ - if (param_extension && (type & 0x0038) && param2) { + if ((param_extension || acpi5) && (type & 0x0038) && param2) { struct apei_resources addr_resources; apei_resources_init(&addr_resources); trigger_param_region = einj_get_trigger_parameter_region( diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c index 903549df809b..04ab5c9d3ced 100644 --- a/drivers/acpi/apei/erst-dbg.c +++ b/drivers/acpi/apei/erst-dbg.c @@ -111,8 +111,17 @@ retry_next: if (rc) goto out; /* no more record */ - if (id == APEI_ERST_INVALID_RECORD_ID) + if (id == APEI_ERST_INVALID_RECORD_ID) { + /* + * If the persistent store is empty initially, the function + * 'erst_read' below will return "-ENOENT" value. This causes + * 'retry_next' label is entered again. The returned value + * should be zero indicating the read operation is EOF. + */ + len = 0; + goto out; + } retry: rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len); /* The record may be cleared by others, try read next record */ diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index e4d9d24eb73d..6d894bfd8b8f 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -931,14 +931,14 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) static int erst_open_pstore(struct pstore_info *psi); static int erst_close_pstore(struct pstore_info *psi); -static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, +static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi); static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, - u64 *id, unsigned int part, + u64 *id, unsigned int part, int count, size_t size, struct pstore_info *psi); -static int erst_clearer(enum pstore_type_id type, u64 id, - struct pstore_info *psi); +static int erst_clearer(enum pstore_type_id type, u64 id, int count, + struct timespec time, struct pstore_info *psi); static struct pstore_info erst_info = { .owner = THIS_MODULE, @@ -987,7 +987,7 @@ static int erst_close_pstore(struct pstore_info *psi) return 0; } -static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, +static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, struct timespec *time, char **buf, struct pstore_info *psi) { @@ -1055,7 +1055,7 @@ out: } static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, - u64 *id, unsigned int part, + u64 *id, unsigned int part, int count, size_t size, struct pstore_info *psi) { struct cper_pstore_record *rcd = (struct cper_pstore_record *) @@ -1101,8 +1101,8 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, return ret; } -static int erst_clearer(enum pstore_type_id type, u64 id, - struct pstore_info *psi) +static int erst_clearer(enum pstore_type_id type, u64 id, int count, + struct timespec time, struct pstore_info *psi) { return erst_clear(id); } diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 1599566ed1fe..d668a8ae602b 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -48,8 +48,8 @@ #include <linux/genalloc.h> #include <linux/pci.h> #include <linux/aer.h> -#include <acpi/apei.h> -#include <acpi/hed.h> + +#include <acpi/ghes.h> #include <asm/mce.h> #include <asm/tlbflush.h> #include <asm/nmi.h> @@ -84,42 +84,6 @@ ((struct acpi_hest_generic_status *) \ ((struct ghes_estatus_node *)(estatus_node) + 1)) -/* - * One struct ghes is created for each generic hardware error source. - * It provides the context for APEI hardware error timer/IRQ/SCI/NMI - * handler. - * - * estatus: memory buffer for error status block, allocated during - * HEST parsing. - */ -#define GHES_TO_CLEAR 0x0001 -#define GHES_EXITING 0x0002 - -struct ghes { - struct acpi_hest_generic *generic; - struct acpi_hest_generic_status *estatus; - u64 buffer_paddr; - unsigned long flags; - union { - struct list_head list; - struct timer_list timer; - unsigned int irq; - }; -}; - -struct ghes_estatus_node { - struct llist_node llnode; - struct acpi_hest_generic *generic; -}; - -struct ghes_estatus_cache { - u32 estatus_len; - atomic_t count; - struct acpi_hest_generic *generic; - unsigned long long time_in; - struct rcu_head rcu; -}; - bool ghes_disable; module_param_named(disable, ghes_disable, bool, 0); @@ -333,13 +297,6 @@ static void ghes_fini(struct ghes *ghes) apei_unmap_generic_address(&ghes->generic->error_status_address); } -enum { - GHES_SEV_NO = 0x0, - GHES_SEV_CORRECTED = 0x1, - GHES_SEV_RECOVERABLE = 0x2, - GHES_SEV_PANIC = 0x3, -}; - static inline int ghes_severity(int severity) { switch (severity) { @@ -452,7 +409,8 @@ static void ghes_clear_estatus(struct ghes *ghes) ghes->flags &= ~GHES_TO_CLEAR; } -static void ghes_do_proc(const struct acpi_hest_generic_status *estatus) +static void ghes_do_proc(struct ghes *ghes, + const struct acpi_hest_generic_status *estatus) { int sev, sec_sev; struct acpi_hest_generic_data *gdata; @@ -464,6 +422,8 @@ static void ghes_do_proc(const struct acpi_hest_generic_status *estatus) CPER_SEC_PLATFORM_MEM)) { struct cper_sec_mem_err *mem_err; mem_err = (struct cper_sec_mem_err *)(gdata+1); + ghes_edac_report_mem_error(ghes, sev, mem_err); + #ifdef CONFIG_X86_MCE apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED, mem_err); @@ -682,7 +642,7 @@ static int ghes_proc(struct ghes *ghes) if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus)) ghes_estatus_cache_add(ghes->generic, ghes->estatus); } - ghes_do_proc(ghes->estatus); + ghes_do_proc(ghes, ghes->estatus); out: ghes_clear_estatus(ghes); return 0; @@ -775,7 +735,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) estatus = GHES_ESTATUS_FROM_NODE(estatus_node); len = apei_estatus_len(estatus); node_len = GHES_ESTATUS_NODE_LEN(len); - ghes_do_proc(estatus); + ghes_do_proc(estatus_node->ghes, estatus); if (!ghes_estatus_cached(estatus)) { generic = estatus_node->generic; if (ghes_print_estatus(NULL, generic, estatus)) @@ -864,6 +824,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool, node_len); if (estatus_node) { + estatus_node->ghes = ghes; estatus_node->generic = ghes->generic; estatus = GHES_ESTATUS_FROM_NODE(estatus_node); memcpy(estatus, ghes->estatus, len); @@ -901,7 +862,7 @@ static unsigned long ghes_esource_prealloc_size( return prealloc_size; } -static int __devinit ghes_probe(struct platform_device *ghes_dev) +static int ghes_probe(struct platform_device *ghes_dev) { struct acpi_hest_generic *generic; struct ghes *ghes = NULL; @@ -942,6 +903,11 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) ghes = NULL; goto err; } + + rc = ghes_edac_register(ghes, &ghes_dev->dev); + if (rc < 0) + goto err; + switch (generic->notify.type) { case ACPI_HEST_NOTIFY_POLLED: ghes->timer.function = ghes_poll_func; @@ -954,13 +920,13 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) if (acpi_gsi_to_irq(generic->notify.vector, &ghes->irq)) { pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n", generic->header.source_id); - goto err; + goto err_edac_unreg; } if (request_irq(ghes->irq, ghes_irq_func, 0, "GHES IRQ", ghes)) { pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n", generic->header.source_id); - goto err; + goto err_edac_unreg; } break; case ACPI_HEST_NOTIFY_SCI: @@ -986,6 +952,8 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) platform_set_drvdata(ghes_dev, ghes); return 0; +err_edac_unreg: + ghes_edac_unregister(ghes); err: if (ghes) { ghes_fini(ghes); @@ -994,7 +962,7 @@ err: return rc; } -static int __devexit ghes_remove(struct platform_device *ghes_dev) +static int ghes_remove(struct platform_device *ghes_dev) { struct ghes *ghes; struct acpi_hest_generic *generic; @@ -1038,6 +1006,9 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev) } ghes_fini(ghes); + + ghes_edac_unregister(ghes); + kfree(ghes); platform_set_drvdata(ghes_dev, NULL); diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 7f00cf38098f..f5ef5d54e4ac 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -89,7 +89,7 @@ int apei_hest_parse(apei_hest_func_t func, void *data) struct acpi_hest_header *hest_hdr; int i, rc, len; - if (hest_disable) + if (hest_disable || !hest_tab) return -EINVAL; hest_hdr = (struct acpi_hest_header *)(hest_tab + 1); @@ -216,9 +216,6 @@ void __init acpi_hest_init(void) return; } - if (acpi_disabled) - goto err; - status = acpi_get_table(ACPI_SIG_HEST, 0, (struct acpi_table_header **)&hest_tab); if (status == AE_NOT_FOUND) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 45e3e1759fb8..c5cd5b5513e6 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -34,6 +34,7 @@ #include <linux/dmi.h> #include <linux/slab.h> #include <linux/suspend.h> +#include <asm/unaligned.h> #ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> @@ -95,6 +96,18 @@ enum { ACPI_BATTERY_ALARM_PRESENT, ACPI_BATTERY_XINFO_PRESENT, ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, + /* On Lenovo Thinkpad models from 2010 and 2011, the power unit + switches between mWh and mAh depending on whether the system + is running on battery or not. When mAh is the unit, most + reported values are incorrect and need to be adjusted by + 10000/design_voltage. Verified on x201, t410, t410s, and x220. + Pre-2010 and 2012 models appear to always report in mWh and + are thus unaffected (tested with t42, t61, t500, x200, x300, + and x230). Also, in mid-2012 Lenovo issued a BIOS update for + the 2011 models that fixes the issue (tested on x220 with a + post-1.29 BIOS), but as of Nov. 2012, no such update is + available for the 2010 models. */ + ACPI_BATTERY_QUIRK_THINKPAD_MAH, }; struct acpi_battery { @@ -438,6 +451,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery) kfree(buffer.pointer); if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) battery->full_charge_capacity = battery->design_capacity; + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && + battery->power_unit && battery->design_voltage) { + battery->design_capacity = battery->design_capacity * + 10000 / battery->design_voltage; + battery->full_charge_capacity = battery->full_charge_capacity * + 10000 / battery->design_voltage; + battery->design_capacity_warning = + battery->design_capacity_warning * + 10000 / battery->design_voltage; + /* Curiously, design_capacity_low, unlike the rest of them, + is correct. */ + /* capacity_granularity_* equal 1 on the systems tested, so + it's impossible to tell if they would need an adjustment + or not if their values were higher. */ + } return result; } @@ -486,6 +514,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery) && battery->capacity_now >= 0 && battery->capacity_now <= 100) battery->capacity_now = (battery->capacity_now * battery->full_charge_capacity) / 100; + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && + battery->power_unit && battery->design_voltage) { + battery->capacity_now = battery->capacity_now * + 10000 / battery->design_voltage; + } return result; } @@ -595,6 +628,24 @@ static void sysfs_remove_battery(struct acpi_battery *battery) mutex_unlock(&battery->sysfs_lock); } +static void find_battery(const struct dmi_header *dm, void *private) +{ + struct acpi_battery *battery = (struct acpi_battery *)private; + /* Note: the hardcoded offsets below have been extracted from + the source code of dmidecode. */ + if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) { + const u8 *dmi_data = (const u8 *)(dm + 1); + int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6)); + if (dm->length >= 18) + dmi_capacity *= dmi_data[17]; + if (battery->design_capacity * battery->design_voltage / 1000 + != dmi_capacity && + battery->design_capacity * 10 == dmi_capacity) + set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, + &battery->flags); + } +} + /* * According to the ACPI spec, some kinds of primary batteries can * report percentage battery remaining capacity directly to OS. @@ -620,6 +671,32 @@ static void acpi_battery_quirks(struct acpi_battery *battery) battery->capacity_now = (battery->capacity_now * battery->full_charge_capacity) / 100; } + + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags)) + return ; + + if (battery->power_unit && dmi_name_in_vendors("LENOVO")) { + const char *s; + s = dmi_get_system_info(DMI_PRODUCT_VERSION); + if (s && !strnicmp(s, "ThinkPad", 8)) { + dmi_walk(find_battery, battery); + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, + &battery->flags) && + battery->design_voltage) { + battery->design_capacity = + battery->design_capacity * + 10000 / battery->design_voltage; + battery->full_charge_capacity = + battery->full_charge_capacity * + 10000 / battery->design_voltage; + battery->design_capacity_warning = + battery->design_capacity_warning * + 10000 / battery->design_voltage; + battery->capacity_now = battery->capacity_now * + 10000 / battery->design_voltage; + } + } + } } static int acpi_battery_update(struct acpi_battery *battery) @@ -1034,7 +1111,7 @@ fail: return result; } -static int acpi_battery_remove(struct acpi_device *device, int type) +static int acpi_battery_remove(struct acpi_device *device) { struct acpi_battery *battery = NULL; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d59175efc428..01708a165368 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -178,261 +178,6 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data) } EXPORT_SYMBOL(acpi_bus_get_private_data); -/* -------------------------------------------------------------------------- - Power Management - -------------------------------------------------------------------------- */ - -static const char *state_string(int state) -{ - switch (state) { - case ACPI_STATE_D0: - return "D0"; - case ACPI_STATE_D1: - return "D1"; - case ACPI_STATE_D2: - return "D2"; - case ACPI_STATE_D3_HOT: - return "D3hot"; - case ACPI_STATE_D3_COLD: - return "D3"; - default: - return "(unknown)"; - } -} - -static int __acpi_bus_get_power(struct acpi_device *device, int *state) -{ - int result = ACPI_STATE_UNKNOWN; - - if (!device || !state) - return -EINVAL; - - if (!device->flags.power_manageable) { - /* TBD: Non-recursive algorithm for walking up hierarchy. */ - *state = device->parent ? - device->parent->power.state : ACPI_STATE_D0; - goto out; - } - - /* - * Get the device's power state either directly (via _PSC) or - * indirectly (via power resources). - */ - if (device->power.flags.explicit_get) { - unsigned long long psc; - acpi_status status = acpi_evaluate_integer(device->handle, - "_PSC", NULL, &psc); - if (ACPI_FAILURE(status)) - return -ENODEV; - - result = psc; - } - /* The test below covers ACPI_STATE_UNKNOWN too. */ - if (result <= ACPI_STATE_D2) { - ; /* Do nothing. */ - } else if (device->power.flags.power_resources) { - int error = acpi_power_get_inferred_state(device, &result); - if (error) - return error; - } 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: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", - device->pnp.bus_id, state_string(*state))); - - return 0; -} - - -static int __acpi_bus_set_power(struct acpi_device *device, int state) -{ - int result = 0; - acpi_status status = AE_OK; - char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; - - if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) - return -EINVAL; - - /* Make sure this is a valid target state */ - - if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", - state_string(state))); - return 0; - } - - if (!device->power.states[state].flags.valid) { - printk(KERN_WARNING PREFIX "Device does not support %s\n", - state_string(state)); - return -ENODEV; - } - if (device->parent && (state < device->parent->power.state)) { - printk(KERN_WARNING PREFIX - "Cannot set device to a higher-powered" - " state than parent\n"); - return -ENODEV; - } - - /* For D3cold we should execute _PS3, not _PS4. */ - if (state == ACPI_STATE_D3_COLD) - object_name[3] = '3'; - - /* - * Transition Power - * ---------------- - * On transitions to a high-powered state we first apply power (via - * power resources) then evalute _PSx. Conversly for transitions to - * a lower-powered state. - */ - if (state < device->power.state) { - if (device->power.flags.power_resources) { - result = acpi_power_transition(device, state); - if (result) - goto end; - } - if (device->power.states[state].flags.explicit_set) { - status = acpi_evaluate_object(device->handle, - object_name, NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - } - } else { - if (device->power.states[state].flags.explicit_set) { - status = acpi_evaluate_object(device->handle, - object_name, NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } - } - if (device->power.flags.power_resources) { - result = acpi_power_transition(device, state); - if (result) - goto end; - } - } - - end: - if (result) - printk(KERN_WARNING PREFIX - "Device [%s] failed to transition to %s\n", - device->pnp.bus_id, state_string(state)); - else { - device->power.state = state; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] transitioned to %s\n", - device->pnp.bus_id, state_string(state))); - } - - return result; -} - - -int acpi_bus_set_power(acpi_handle handle, int state) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] is not power manageable\n", - dev_name(&device->dev))); - return -ENODEV; - } - - return __acpi_bus_set_power(device, state); -} -EXPORT_SYMBOL(acpi_bus_set_power); - - -int acpi_bus_init_power(struct acpi_device *device) -{ - int state; - int result; - - if (!device) - return -EINVAL; - - device->power.state = ACPI_STATE_UNKNOWN; - - result = __acpi_bus_get_power(device, &state); - if (result) - return result; - - if (device->power.flags.power_resources) - result = acpi_power_on_resources(device, state); - - if (!result) - device->power.state = state; - - return result; -} - - -int acpi_bus_update_power(acpi_handle handle, int *state_p) -{ - struct acpi_device *device; - int state; - int result; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - result = __acpi_bus_get_power(device, &state); - if (result) - return result; - - result = __acpi_bus_set_power(device, state); - if (!result && state_p) - *state_p = state; - - return result; -} -EXPORT_SYMBOL_GPL(acpi_bus_update_power); - - -bool acpi_bus_power_manageable(acpi_handle handle) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - return result ? false : device->flags.power_manageable; -} - -EXPORT_SYMBOL(acpi_bus_power_manageable); - -bool acpi_bus_can_wakeup(acpi_handle handle) -{ - struct acpi_device *device; - int result; - - result = acpi_bus_get_device(handle, &device); - return result ? false : device->wakeup.flags.valid; -} - -EXPORT_SYMBOL(acpi_bus_can_wakeup); - static void acpi_print_osc_error(acpi_handle handle, struct acpi_osc_context *context, char *error) { diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index f0d936b65e37..86c7d5445c38 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -75,7 +75,7 @@ static const struct acpi_device_id button_device_ids[] = { MODULE_DEVICE_TABLE(acpi, button_device_ids); static int acpi_button_add(struct acpi_device *device); -static int acpi_button_remove(struct acpi_device *device, int type); +static int acpi_button_remove(struct acpi_device *device); static void acpi_button_notify(struct acpi_device *device, u32 event); #ifdef CONFIG_PM_SLEEP @@ -433,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device) return error; } -static int acpi_button_remove(struct acpi_device *device, int type) +static int acpi_button_remove(struct acpi_device *device) { struct acpi_button *button = acpi_driver_data(device); diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 1f9f7d7d7bc5..5523ba7d764d 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -34,46 +34,34 @@ #include <linux/acpi.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> -#include <acpi/container.h> #define PREFIX "ACPI: " -#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" -#define ACPI_CONTAINER_CLASS "container" - -#define INSTALL_NOTIFY_HANDLER 1 -#define UNINSTALL_NOTIFY_HANDLER 2 - #define _COMPONENT ACPI_CONTAINER_COMPONENT ACPI_MODULE_NAME("container"); -MODULE_AUTHOR("Anil S Keshavamurthy"); -MODULE_DESCRIPTION("ACPI container driver"); -MODULE_LICENSE("GPL"); - -static int acpi_container_add(struct acpi_device *device); -static int acpi_container_remove(struct acpi_device *device, int type); - static const struct acpi_device_id container_device_ids[] = { {"ACPI0004", 0}, {"PNP0A05", 0}, {"PNP0A06", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, container_device_ids); -static struct acpi_driver acpi_container_driver = { - .name = "container", - .class = ACPI_CONTAINER_CLASS, +static int container_device_attach(struct acpi_device *device, + const struct acpi_device_id *not_used) +{ + /* + * FIXME: This is necessary, so that acpi_eject_store() doesn't return + * -ENODEV for containers. + */ + return 1; +} + +static struct acpi_scan_handler container_device_handler = { .ids = container_device_ids, - .ops = { - .add = acpi_container_add, - .remove = acpi_container_remove, - }, + .attach = container_device_attach, }; -/*******************************************************************/ - static int is_device_present(acpi_handle handle) { acpi_handle temp; @@ -92,66 +80,6 @@ static int is_device_present(acpi_handle handle) return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); } -/*******************************************************************/ -static int acpi_container_add(struct acpi_device *device) -{ - struct acpi_container *container; - - - if (!device) { - printk(KERN_ERR PREFIX "device is NULL\n"); - return -EINVAL; - } - - container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL); - if (!container) - return -ENOMEM; - - container->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); - device->driver_data = container; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", - acpi_device_name(device), acpi_device_bid(device))); - - return 0; -} - -static int acpi_container_remove(struct acpi_device *device, int type) -{ - acpi_status status = AE_OK; - struct acpi_container *pc = NULL; - - pc = acpi_driver_data(device); - kfree(pc); - return status; -} - -static int container_device_add(struct acpi_device **device, acpi_handle handle) -{ - acpi_handle phandle; - struct acpi_device *pdev; - int result; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } - - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { - return -ENODEV; - } - - result = acpi_bus_start(*device); - - return result; -} - static void container_notify_cb(acpi_handle handle, u32 type, void *context) { struct acpi_device *device = NULL; @@ -160,11 +88,13 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) acpi_status status; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_scan_lock_acquire(); + switch (type) { case ACPI_NOTIFY_BUS_CHECK: /* Fall through */ case ACPI_NOTIFY_DEVICE_CHECK: - printk(KERN_WARNING "Container driver received %s event\n", + pr_debug("Container driver received %s event\n", (type == ACPI_NOTIFY_BUS_CHECK) ? "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); @@ -175,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) /* device exist and this is a remove request */ device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - return; + goto out; } break; } @@ -183,9 +113,14 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!ACPI_FAILURE(status) || device) break; - result = container_device_add(&device, handle); + result = acpi_bus_scan(handle); if (result) { - printk(KERN_WARNING "Failed to add container\n"); + acpi_handle_warn(handle, "Failed to add container\n"); + break; + } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); break; } @@ -197,100 +132,59 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) if (!acpi_bus_get_device(handle, &device) && device) { device->flags.eject_pending = 1; kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); - return; + goto out; } break; default: /* non-hotplug event; possibly handled by other handler */ - return; + goto out; } /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); - return; + + out: + acpi_scan_lock_release(); } -static acpi_status -container_walk_namespace_cb(acpi_handle handle, - u32 lvl, void *context, void **rv) +static bool is_container(acpi_handle handle) { - char *hid = NULL; struct acpi_device_info *info; - acpi_status status; - int *action = context; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { - return AE_OK; - } - - if (info->valid & ACPI_VALID_HID) - hid = info->hardware_id.string; + bool ret = false; - if (hid == NULL) { - goto end; - } + if (ACPI_FAILURE(acpi_get_object_info(handle, &info))) + return false; - if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") && - strcmp(hid, "PNP0A06")) { - goto end; - } + if (info->valid & ACPI_VALID_HID) { + const struct acpi_device_id *id; - switch (*action) { - case INSTALL_NOTIFY_HANDLER: - acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - container_notify_cb, NULL); - break; - case UNINSTALL_NOTIFY_HANDLER: - acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - container_notify_cb); - break; - default: - break; + for (id = container_device_ids; id->id[0]; id++) { + ret = !strcmp((char *)id->id, info->hardware_id.string); + if (ret) + break; + } } - - end: kfree(info); - - return AE_OK; + return ret; } -static int __init acpi_container_init(void) +static acpi_status acpi_container_register_notify_handler(acpi_handle handle, + u32 lvl, void *ctxt, + void **retv) { - int result = 0; - int action = INSTALL_NOTIFY_HANDLER; - - result = acpi_bus_register_driver(&acpi_container_driver); - if (result < 0) { - return (result); - } - - /* register notify handler to every container device */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - container_walk_namespace_cb, NULL, &action, NULL); + if (is_container(handle)) + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + container_notify_cb, NULL); - return (0); + return AE_OK; } -static void __exit acpi_container_exit(void) +void __init acpi_container_init(void) { - int action = UNINSTALL_NOTIFY_HANDLER; + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_container_register_notify_handler, NULL, + NULL, NULL); - - acpi_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - container_walk_namespace_cb, NULL, &action, NULL); - - acpi_bus_unregister_driver(&acpi_container_driver); - - return; + acpi_scan_add_handler(&container_device_handler); } - -module_init(acpi_container_init); -module_exit(acpi_container_exit); diff --git a/drivers/acpi/csrt.c b/drivers/acpi/csrt.c new file mode 100644 index 000000000000..5c15a91faf0b --- /dev/null +++ b/drivers/acpi/csrt.c @@ -0,0 +1,159 @@ +/* + * Support for Core System Resources Table (CSRT) + * + * Copyright (C) 2013, Intel Corporation + * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> + * Andy Shevchenko <andriy.shevchenko@linux.intel.com> + * + * 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 + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "ACPI: CSRT: " fmt + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/sizes.h> + +ACPI_MODULE_NAME("CSRT"); + +static int __init acpi_csrt_parse_shared_info(struct platform_device *pdev, + const struct acpi_csrt_group *grp) +{ + const struct acpi_csrt_shared_info *si; + struct resource res[3]; + size_t nres; + int ret; + + memset(res, 0, sizeof(res)); + nres = 0; + + si = (const struct acpi_csrt_shared_info *)&grp[1]; + /* + * The peripherals that are listed on CSRT typically support only + * 32-bit addresses so we only use the low part of MMIO base for + * now. + */ + if (!si->mmio_base_high && si->mmio_base_low) { + /* + * There is no size of the memory resource in shared_info + * so we assume that it is 4k here. + */ + res[nres].start = si->mmio_base_low; + res[nres].end = res[0].start + SZ_4K - 1; + res[nres++].flags = IORESOURCE_MEM; + } + + if (si->gsi_interrupt) { + int irq = acpi_register_gsi(NULL, si->gsi_interrupt, + si->interrupt_mode, + si->interrupt_polarity); + res[nres].start = irq; + res[nres].end = irq; + res[nres++].flags = IORESOURCE_IRQ; + } + + if (si->base_request_line || si->num_handshake_signals) { + /* + * We pass the driver a DMA resource describing the range + * of request lines the device supports. + */ + res[nres].start = si->base_request_line; + res[nres].end = res[nres].start + si->num_handshake_signals - 1; + res[nres++].flags = IORESOURCE_DMA; + } + + ret = platform_device_add_resources(pdev, res, nres); + if (ret) { + if (si->gsi_interrupt) + acpi_unregister_gsi(si->gsi_interrupt); + return ret; + } + + return 0; +} + +static int __init +acpi_csrt_parse_resource_group(const struct acpi_csrt_group *grp) +{ + struct platform_device *pdev; + char vendor[5], name[16]; + int ret, i; + + vendor[0] = grp->vendor_id; + vendor[1] = grp->vendor_id >> 8; + vendor[2] = grp->vendor_id >> 16; + vendor[3] = grp->vendor_id >> 24; + vendor[4] = '\0'; + + if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info)) + return -ENODEV; + + snprintf(name, sizeof(name), "%s%04X", vendor, grp->device_id); + pdev = platform_device_alloc(name, PLATFORM_DEVID_AUTO); + if (!pdev) + return -ENOMEM; + + /* Add resources based on the shared info */ + ret = acpi_csrt_parse_shared_info(pdev, grp); + if (ret) + goto fail; + + ret = platform_device_add(pdev); + if (ret) + goto fail; + + for (i = 0; i < pdev->num_resources; i++) + dev_dbg(&pdev->dev, "%pR\n", &pdev->resource[i]); + + return 0; + +fail: + platform_device_put(pdev); + return ret; +} + +/* + * CSRT or Core System Resources Table is a proprietary ACPI table + * introduced by Microsoft. This table can contain devices that are not in + * the system DSDT table. In particular DMA controllers might be described + * here. + * + * We present these devices as normal platform devices that don't have ACPI + * IDs or handle. The platform device name will be something like + * <VENDOR><DEVID>.<n>.auto for example: INTL9C06.0.auto. + */ +void __init acpi_csrt_init(void) +{ + struct acpi_csrt_group *grp, *end; + struct acpi_table_csrt *csrt; + acpi_status status; + int ret; + + status = acpi_get_table(ACPI_SIG_CSRT, 0, + (struct acpi_table_header **)&csrt); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + pr_warn("failed to get the CSRT table\n"); + return; + } + + pr_debug("parsing CSRT table for devices\n"); + + grp = (struct acpi_csrt_group *)(csrt + 1); + end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length); + + while (grp < end) { + ret = acpi_csrt_parse_resource_group(grp); + if (ret) { + pr_warn("error in parsing resource group: %d\n", ret); + return; + } + + grp = (struct acpi_csrt_group *)((void *)grp + grp->length); + } +} diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c index 5d42c2414ae5..12b62f2cdb3f 100644 --- a/drivers/acpi/custom_method.c +++ b/drivers/acpi/custom_method.c @@ -1,5 +1,5 @@ /* - * debugfs.c - ACPI debugfs interface to userspace. + * custom_method.c - debugfs interface for customizing ACPI control method */ #include <linux/init.h> @@ -66,7 +66,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, buf = NULL; if (ACPI_FAILURE(status)) return -EINVAL; - add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); + add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); } return count; diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c new file mode 100644 index 000000000000..dd314ef9bff1 --- /dev/null +++ b/drivers/acpi/device_pm.c @@ -0,0 +1,1016 @@ +/* + * drivers/acpi/device_pm.c - ACPI device power management routines. + * + * Copyright (C) 2012, Intel Corp. + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include <linux/device.h> +#include <linux/export.h> +#include <linux/mutex.h> +#include <linux/pm_qos.h> +#include <linux/pm_runtime.h> + +#include <acpi/acpi.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> + +#include "internal.h" + +#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. + */ +const char *acpi_power_state_string(int state) +{ + switch (state) { + case ACPI_STATE_D0: + return "D0"; + case ACPI_STATE_D1: + return "D1"; + case ACPI_STATE_D2: + return "D2"; + case ACPI_STATE_D3_HOT: + return "D3hot"; + case ACPI_STATE_D3_COLD: + return "D3cold"; + default: + return "(unknown)"; + } +} + +/** + * acpi_device_get_power - Get power state of an ACPI device. + * @device: Device to get the power state of. + * @state: Place to store the power state of the device. + * + * This function does not update the device's power.state field, but it may + * update its parent's power.state field (when the parent's power state is + * unknown and the device's power state turns out to be D0). + */ +int acpi_device_get_power(struct acpi_device *device, int *state) +{ + int result = ACPI_STATE_UNKNOWN; + + if (!device || !state) + return -EINVAL; + + if (!device->flags.power_manageable) { + /* TBD: Non-recursive algorithm for walking up hierarchy. */ + *state = device->parent ? + device->parent->power.state : ACPI_STATE_D0; + goto out; + } + + /* + * Get the device's power state either directly (via _PSC) or + * indirectly (via power resources). + */ + if (device->power.flags.explicit_get) { + unsigned long long psc; + acpi_status status = acpi_evaluate_integer(device->handle, + "_PSC", NULL, &psc); + if (ACPI_FAILURE(status)) + return -ENODEV; + + result = psc; + } + /* The test below covers ACPI_STATE_UNKNOWN too. */ + if (result <= ACPI_STATE_D2) { + ; /* Do nothing. */ + } else if (device->power.flags.power_resources) { + int error = acpi_power_get_inferred_state(device, &result); + if (error) + return error; + } 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: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", + device->pnp.bus_id, acpi_power_state_string(*state))); + + return 0; +} + +static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) +{ + if (adev->power.states[state].flags.explicit_set) { + char method[5] = { '_', 'P', 'S', '0' + state, '\0' }; + acpi_status status; + + status = acpi_evaluate_object(adev->handle, method, NULL, NULL); + if (ACPI_FAILURE(status)) + return -ENODEV; + } + return 0; +} + +/** + * acpi_device_set_power - Set power state of an ACPI device. + * @device: Device to set the power state of. + * @state: New power state to set. + * + * Callers must ensure that the device is power manageable before using this + * function. + */ +int acpi_device_set_power(struct acpi_device *device, int state) +{ + int result = 0; + bool cut_power = false; + + if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) + return -EINVAL; + + /* Make sure this is a valid target state */ + + if (state == device->power.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", + acpi_power_state_string(state))); + return 0; + } + + if (!device->power.states[state].flags.valid) { + printk(KERN_WARNING PREFIX "Device does not support %s\n", + acpi_power_state_string(state)); + return -ENODEV; + } + if (device->parent && (state < device->parent->power.state)) { + printk(KERN_WARNING PREFIX + "Cannot set device to a higher-powered" + " state than parent\n"); + return -ENODEV; + } + + /* For D3cold we should first transition into D3hot. */ + if (state == ACPI_STATE_D3_COLD + && device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible) { + state = ACPI_STATE_D3_HOT; + cut_power = true; + } + + if (state < device->power.state && state != ACPI_STATE_D0 + && device->power.state >= ACPI_STATE_D3_HOT) { + printk(KERN_WARNING PREFIX + "Cannot transition to non-D0 state from D3\n"); + return -ENODEV; + } + + /* + * Transition Power + * ---------------- + * In accordance with the ACPI specification first apply power (via + * power resources) and then evalute _PSx. + */ + if (device->power.flags.power_resources) { + result = acpi_power_transition(device, state); + if (result) + goto end; + } + result = acpi_dev_pm_explicit_set(device, state); + if (result) + goto end; + + if (cut_power) { + device->power.state = state; + state = ACPI_STATE_D3_COLD; + result = acpi_power_transition(device, state); + } + + end: + if (result) { + printk(KERN_WARNING PREFIX + "Device [%s] failed to transition to %s\n", + device->pnp.bus_id, + acpi_power_state_string(state)); + } else { + device->power.state = state; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device [%s] transitioned to %s\n", + device->pnp.bus_id, + acpi_power_state_string(state))); + } + + return result; +} +EXPORT_SYMBOL(acpi_device_set_power); + +int acpi_bus_set_power(acpi_handle handle, int state) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + if (result) + return result; + + if (!device->flags.power_manageable) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Device [%s] is not power manageable\n", + dev_name(&device->dev))); + return -ENODEV; + } + + return acpi_device_set_power(device, state); +} +EXPORT_SYMBOL(acpi_bus_set_power); + +int acpi_bus_init_power(struct acpi_device *device) +{ + int state; + int result; + + if (!device) + return -EINVAL; + + device->power.state = ACPI_STATE_UNKNOWN; + + result = acpi_device_get_power(device, &state); + if (result) + return result; + + if (state < ACPI_STATE_D3_COLD && device->power.flags.power_resources) { + result = acpi_power_on_resources(device, state); + if (result) + return result; + + result = acpi_dev_pm_explicit_set(device, state); + if (result) + return result; + } else if (state == ACPI_STATE_UNKNOWN) { + /* No power resources and missing _PSC? Try to force D0. */ + state = ACPI_STATE_D0; + result = acpi_dev_pm_explicit_set(device, state); + if (result) + return result; + } + device->power.state = state; + return 0; +} + +int acpi_bus_update_power(acpi_handle handle, int *state_p) +{ + struct acpi_device *device; + int state; + int result; + + result = acpi_bus_get_device(handle, &device); + if (result) + return result; + + result = acpi_device_get_power(device, &state); + if (result) + return result; + + if (state == ACPI_STATE_UNKNOWN) + state = ACPI_STATE_D0; + + result = acpi_device_set_power(device, state); + if (!result && state_p) + *state_p = state; + + return result; +} +EXPORT_SYMBOL_GPL(acpi_bus_update_power); + +bool acpi_bus_power_manageable(acpi_handle handle) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + return result ? false : device->flags.power_manageable; +} +EXPORT_SYMBOL(acpi_bus_power_manageable); + +bool acpi_bus_can_wakeup(acpi_handle handle) +{ + struct acpi_device *device; + int result; + + result = acpi_bus_get_device(handle, &device); + return result ? false : device->wakeup.flags.valid; +} +EXPORT_SYMBOL(acpi_bus_can_wakeup); + +/** + * acpi_device_power_state - Get preferred power state of ACPI device. + * @dev: Device whose preferred target power state to return. + * @adev: ACPI device node corresponding to @dev. + * @target_state: System state to match the resultant device state. + * @d_max_in: Deepest low-power state to take into consideration. + * @d_min_p: Location to store the upper limit of the allowed states range. + * Return value: Preferred power state of the device on success, -ENODEV + * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure + * + * Find the lowest power (highest number) ACPI device power state that the + * device can be in while the system is in the state represented by + * @target_state. If @d_min_p is set, the highest power (lowest number) device + * power state that @dev can be in for the given system sleep state is stored + * at the location pointed to by it. + * + * Callers must ensure that @dev and @adev are valid pointers and that @adev + * actually corresponds to @dev before using this function. + */ +int acpi_device_power_state(struct device *dev, struct acpi_device *adev, + u32 target_state, int d_max_in, int *d_min_p) +{ + char acpi_method[] = "_SxD"; + unsigned long long d_min, d_max; + bool wakeup = false; + + if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3) + return -EINVAL; + + if (d_max_in > ACPI_STATE_D3_HOT) { + enum pm_qos_flags_status stat; + + stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF); + if (stat == PM_QOS_FLAGS_ALL) + d_max_in = ACPI_STATE_D3_HOT; + } + + acpi_method[2] = '0' + target_state; + /* + * If the sleep state is S0, the lowest limit from ACPI is D3, + * but if the device has _S0W, we will use the value from _S0W + * as the lowest limit from ACPI. Finally, we will constrain + * the lowest limit with the specified one. + */ + d_min = ACPI_STATE_D0; + d_max = ACPI_STATE_D3; + + /* + * If present, _SxD methods return the minimum D-state (highest power + * state) we can use for the corresponding S-states. Otherwise, the + * minimum D-state is D0 (ACPI 3.x). + * + * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer + * provided -- that's our fault recovery, we ignore retval. + */ + if (target_state > ACPI_STATE_S0) { + acpi_evaluate_integer(adev->handle, acpi_method, NULL, &d_min); + wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid + && adev->wakeup.sleep_state >= target_state; + } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) != + PM_QOS_FLAGS_NONE) { + wakeup = adev->wakeup.flags.valid; + } + + /* + * If _PRW says we can wake up the system from the target sleep state, + * the D-state returned by _SxD is sufficient for that (we assume a + * wakeup-aware driver if wake is set). Still, if _SxW exists + * (ACPI 3.x), it should return the maximum (lowest power) D-state that + * can wake the system. _S0W may be valid, too. + */ + if (wakeup) { + acpi_status status; + + acpi_method[3] = 'W'; + status = acpi_evaluate_integer(adev->handle, acpi_method, NULL, + &d_max); + if (ACPI_FAILURE(status)) { + if (target_state != ACPI_STATE_S0 || + status != AE_NOT_FOUND) + d_max = d_min; + } else if (d_max < d_min) { + /* Warn the user of the broken DSDT */ + printk(KERN_WARNING "ACPI: Wrong value from %s\n", + acpi_method); + /* Sanitize it */ + d_min = d_max; + } + } + + if (d_max_in < d_min) + return -EINVAL; + if (d_min_p) + *d_min_p = d_min; + /* constrain d_max with specified lowest limit (max number) */ + if (d_max > d_max_in) { + for (d_max = d_max_in; d_max > d_min; d_max--) { + if (adev->power.states[d_max].flags.valid) + break; + } + } + return d_max; +} +EXPORT_SYMBOL_GPL(acpi_device_power_state); + +/** + * acpi_pm_device_sleep_state - Get preferred power state of ACPI device. + * @dev: Device whose preferred target power state to return. + * @d_min_p: Location to store the upper limit of the allowed states range. + * @d_max_in: Deepest low-power state to take into consideration. + * Return value: Preferred power state of the device on success, -ENODEV + * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure + * + * The caller must ensure that @dev is valid before using this function. + */ +int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + struct acpi_device *adev; + + if (!handle || acpi_bus_get_device(handle, &adev)) { + dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); + return -ENODEV; + } + + return acpi_device_power_state(dev, adev, acpi_target_system_state(), + d_max_in, d_min_p); +} +EXPORT_SYMBOL(acpi_pm_device_sleep_state); + +#ifdef CONFIG_PM_RUNTIME +/** + * acpi_wakeup_device - Wakeup notification handler for ACPI devices. + * @handle: ACPI handle of the device the notification is for. + * @event: Type of the signaled event. + * @context: Device corresponding to @handle. + */ +static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) +{ + struct device *dev = context; + + if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) { + pm_wakeup_event(dev, 0); + pm_runtime_resume(dev); + } +} + +/** + * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device. + * @adev: ACPI device to enable/disable the remote wakeup for. + * @enable: Whether to enable or disable the wakeup functionality. + * + * Enable/disable the GPE associated with @adev so that it can generate + * wakeup signals for the device in response to external (remote) events and + * enable/disable device wakeup power. + * + * Callers must ensure that @adev is a valid ACPI device node before executing + * this function. + */ +int __acpi_device_run_wake(struct acpi_device *adev, bool enable) +{ + struct acpi_device_wakeup *wakeup = &adev->wakeup; + + if (enable) { + acpi_status res; + int error; + + error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0); + if (error) + return error; + + res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); + if (ACPI_FAILURE(res)) { + acpi_disable_wakeup_device_power(adev); + return -EIO; + } + } else { + acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); + acpi_disable_wakeup_device_power(adev); + } + return 0; +} + +/** + * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. + * @dev: Device to enable/disable the platform to wake up. + * @enable: Whether to enable or disable the wakeup functionality. + */ +int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) +{ + struct acpi_device *adev; + acpi_handle handle; + + if (!device_run_wake(phys_dev)) + return -EINVAL; + + handle = DEVICE_ACPI_HANDLE(phys_dev); + if (!handle || acpi_bus_get_device(handle, &adev)) { + dev_dbg(phys_dev, "ACPI handle without context in %s!\n", + __func__); + return -ENODEV; + } + + return __acpi_device_run_wake(adev, enable); +} +EXPORT_SYMBOL(acpi_pm_device_run_wake); +#else +static inline void acpi_wakeup_device(acpi_handle handle, u32 event, + void *context) {} +#endif /* CONFIG_PM_RUNTIME */ + +#ifdef CONFIG_PM_SLEEP +/** + * __acpi_device_sleep_wake - Enable or disable device to wake up the system. + * @dev: Device to enable/desible to wake up the system. + * @target_state: System state the device is supposed to wake up from. + * @enable: Whether to enable or disable @dev to wake up the system. + */ +int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state, + bool enable) +{ + return enable ? + acpi_enable_wakeup_device_power(adev, target_state) : + acpi_disable_wakeup_device_power(adev); +} + +/** + * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. + * @dev: Device to enable/desible to wake up the system from sleep states. + * @enable: Whether to enable or disable @dev to wake up the system. + */ +int acpi_pm_device_sleep_wake(struct device *dev, bool enable) +{ + acpi_handle handle; + struct acpi_device *adev; + int error; + + if (!device_can_wakeup(dev)) + return -EINVAL; + + handle = DEVICE_ACPI_HANDLE(dev); + if (!handle || acpi_bus_get_device(handle, &adev)) { + dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); + return -ENODEV; + } + + error = __acpi_device_sleep_wake(adev, acpi_target_system_state(), + enable); + if (!error) + dev_info(dev, "System wakeup %s by ACPI\n", + enable ? "enabled" : "disabled"); + + return error; +} +#endif /* CONFIG_PM_SLEEP */ + +/** + * acpi_dev_pm_get_node - Get ACPI device node for the given physical device. + * @dev: Device to get the ACPI node for. + */ +struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +{ + acpi_handle handle = DEVICE_ACPI_HANDLE(dev); + struct acpi_device *adev; + + return handle && !acpi_bus_get_device(handle, &adev) ? adev : NULL; +} + +/** + * acpi_dev_pm_low_power - Put ACPI device into a low-power state. + * @dev: Device to put into a low-power state. + * @adev: ACPI device node corresponding to @dev. + * @system_state: System state to choose the device state for. + */ +static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, + u32 system_state) +{ + int power_state; + + if (!acpi_device_power_manageable(adev)) + return 0; + + power_state = acpi_device_power_state(dev, adev, system_state, + ACPI_STATE_D3, NULL); + if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3) + return -EIO; + + return acpi_device_set_power(adev, power_state); +} + +/** + * acpi_dev_pm_full_power - Put ACPI device into the full-power state. + * @adev: ACPI device node to put into the full-power state. + */ +static int acpi_dev_pm_full_power(struct acpi_device *adev) +{ + return acpi_device_power_manageable(adev) ? + acpi_device_set_power(adev, ACPI_STATE_D0) : 0; +} + +#ifdef CONFIG_PM_RUNTIME +/** + * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI. + * @dev: Device to put into a low-power state. + * + * Put the given device into a runtime low-power state using the standard ACPI + * mechanism. Set up remote wakeup if desired, choose the state to put the + * device into (this checks if remote wakeup is expected to work too), and set + * the power state of the device. + */ +int acpi_dev_runtime_suspend(struct device *dev) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + bool remote_wakeup; + int error; + + if (!adev) + return 0; + + remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > + PM_QOS_FLAGS_NONE; + error = __acpi_device_run_wake(adev, remote_wakeup); + if (remote_wakeup && error) + return -EAGAIN; + + error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); + if (error) + __acpi_device_run_wake(adev, false); + + return error; +} +EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend); + +/** + * acpi_dev_runtime_resume - Put device into the full-power state using ACPI. + * @dev: Device to put into the full-power state. + * + * Put the given device into the full-power state using the standard ACPI + * mechanism at run time. Set the power state of the device to ACPI D0 and + * disable remote wakeup. + */ +int acpi_dev_runtime_resume(struct device *dev) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + int error; + + if (!adev) + return 0; + + error = acpi_dev_pm_full_power(adev); + __acpi_device_run_wake(adev, false); + return error; +} +EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); + +/** + * acpi_subsys_runtime_suspend - Suspend device using ACPI. + * @dev: Device to suspend. + * + * Carry out the generic runtime suspend procedure for @dev and use ACPI to put + * it into a runtime low-power state. + */ +int acpi_subsys_runtime_suspend(struct device *dev) +{ + int ret = pm_generic_runtime_suspend(dev); + return ret ? ret : acpi_dev_runtime_suspend(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend); + +/** + * acpi_subsys_runtime_resume - Resume device using ACPI. + * @dev: Device to Resume. + * + * Use ACPI to put the given device into the full-power state and carry out the + * generic runtime resume procedure for it. + */ +int acpi_subsys_runtime_resume(struct device *dev) +{ + int ret = acpi_dev_runtime_resume(dev); + return ret ? ret : pm_generic_runtime_resume(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume); +#endif /* CONFIG_PM_RUNTIME */ + +#ifdef CONFIG_PM_SLEEP +/** + * acpi_dev_suspend_late - Put device into a low-power state using ACPI. + * @dev: Device to put into a low-power state. + * + * Put the given device into a low-power state during system transition to a + * sleep state using the standard ACPI mechanism. Set up system wakeup if + * desired, choose the state to put the device into (this checks if system + * wakeup is expected to work too), and set the power state of the device. + */ +int acpi_dev_suspend_late(struct device *dev) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + u32 target_state; + bool wakeup; + int error; + + if (!adev) + return 0; + + target_state = acpi_target_system_state(); + wakeup = device_may_wakeup(dev); + error = __acpi_device_sleep_wake(adev, target_state, wakeup); + if (wakeup && error) + return error; + + error = acpi_dev_pm_low_power(dev, adev, target_state); + if (error) + __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); + + return error; +} +EXPORT_SYMBOL_GPL(acpi_dev_suspend_late); + +/** + * acpi_dev_resume_early - Put device into the full-power state using ACPI. + * @dev: Device to put into the full-power state. + * + * Put the given device into the full-power state using the standard ACPI + * mechanism during system transition to the working state. Set the power + * state of the device to ACPI D0 and disable remote wakeup. + */ +int acpi_dev_resume_early(struct device *dev) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + int error; + + if (!adev) + return 0; + + error = acpi_dev_pm_full_power(adev); + __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); + return error; +} +EXPORT_SYMBOL_GPL(acpi_dev_resume_early); + +/** + * acpi_subsys_prepare - Prepare device for system transition to a sleep state. + * @dev: Device to prepare. + */ +int acpi_subsys_prepare(struct device *dev) +{ + /* + * Follow PCI and resume devices suspended at run time before running + * their system suspend callbacks. + */ + pm_runtime_resume(dev); + return pm_generic_prepare(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_prepare); + +/** + * acpi_subsys_suspend_late - Suspend device using ACPI. + * @dev: Device to suspend. + * + * Carry out the generic late suspend procedure for @dev and use ACPI to put + * it into a low-power state during system transition into a sleep state. + */ +int acpi_subsys_suspend_late(struct device *dev) +{ + int ret = pm_generic_suspend_late(dev); + return ret ? ret : acpi_dev_suspend_late(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); + +/** + * acpi_subsys_resume_early - Resume device using ACPI. + * @dev: Device to Resume. + * + * Use ACPI to put the given device into the full-power state and carry out the + * generic early resume procedure for it during system transition into the + * working state. + */ +int acpi_subsys_resume_early(struct device *dev) +{ + int ret = acpi_dev_resume_early(dev); + return ret ? ret : pm_generic_resume_early(dev); +} +EXPORT_SYMBOL_GPL(acpi_subsys_resume_early); +#endif /* CONFIG_PM_SLEEP */ + +static struct dev_pm_domain acpi_general_pm_domain = { + .ops = { +#ifdef CONFIG_PM_RUNTIME + .runtime_suspend = acpi_subsys_runtime_suspend, + .runtime_resume = acpi_subsys_runtime_resume, + .runtime_idle = pm_generic_runtime_idle, +#endif +#ifdef CONFIG_PM_SLEEP + .prepare = acpi_subsys_prepare, + .suspend_late = acpi_subsys_suspend_late, + .resume_early = acpi_subsys_resume_early, + .poweroff_late = acpi_subsys_suspend_late, + .restore_early = acpi_subsys_resume_early, +#endif + }, +}; + +/** + * acpi_dev_pm_attach - Prepare device for ACPI power management. + * @dev: Device to prepare. + * @power_on: Whether or not to power on the device. + * + * If @dev has a valid ACPI handle that has a valid struct acpi_device object + * attached to it, install a wakeup notification handler for the device and + * add it to the general ACPI PM domain. If @power_on is set, the device will + * be put into the ACPI D0 state before the function returns. + * + * This assumes that the @dev's bus type uses generic power management callbacks + * (or doesn't use any power management callbacks at all). + * + * Callers must ensure proper synchronization of this function with power + * management callbacks. + */ +int acpi_dev_pm_attach(struct device *dev, bool power_on) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + + if (!adev) + return -ENODEV; + + if (dev->pm_domain) + return -EEXIST; + + acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); + dev->pm_domain = &acpi_general_pm_domain; + if (power_on) { + acpi_dev_pm_full_power(adev); + __acpi_device_run_wake(adev, false); + } + return 0; +} +EXPORT_SYMBOL_GPL(acpi_dev_pm_attach); + +/** + * acpi_dev_pm_detach - Remove ACPI power management from the device. + * @dev: Device to take care of. + * @power_off: Whether or not to try to remove power from the device. + * + * Remove the device from the general ACPI PM domain and remove its wakeup + * notifier. If @power_off is set, additionally remove power from the device if + * possible. + * + * Callers must ensure proper synchronization of this function with power + * management callbacks. + */ +void acpi_dev_pm_detach(struct device *dev, bool power_off) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + + if (adev && dev->pm_domain == &acpi_general_pm_domain) { + dev->pm_domain = NULL; + acpi_remove_pm_notifier(adev, acpi_wakeup_device); + if (power_off) { + /* + * If the device's PM QoS resume latency limit or flags + * have been exposed to user space, they have to be + * hidden at this point, so that they don't affect the + * choice of the low-power state to put the device into. + */ + dev_pm_qos_hide_latency_limit(dev); + dev_pm_qos_hide_flags(dev); + __acpi_device_run_wake(adev, false); + acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); + } + } +} +EXPORT_SYMBOL_GPL(acpi_dev_pm_detach); + +/** + * acpi_dev_pm_add_dependent - Add physical device depending for PM. + * @handle: Handle of ACPI device node. + * @depdev: Device depending on that node for PM. + */ +void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev) +{ + struct acpi_device_physical_node *dep; + struct acpi_device *adev; + + if (!depdev || acpi_bus_get_device(handle, &adev)) + return; + + mutex_lock(&adev->physical_node_lock); + + list_for_each_entry(dep, &adev->power_dependent, node) + if (dep->dev == depdev) + goto out; + + dep = kzalloc(sizeof(*dep), GFP_KERNEL); + if (dep) { + dep->dev = depdev; + list_add_tail(&dep->node, &adev->power_dependent); + } + + out: + mutex_unlock(&adev->physical_node_lock); +} +EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent); + +/** + * acpi_dev_pm_remove_dependent - Remove physical device depending for PM. + * @handle: Handle of ACPI device node. + * @depdev: Device depending on that node for PM. + */ +void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev) +{ + struct acpi_device_physical_node *dep; + struct acpi_device *adev; + + if (!depdev || acpi_bus_get_device(handle, &adev)) + return; + + mutex_lock(&adev->physical_node_lock); + + list_for_each_entry(dep, &adev->power_dependent, node) + if (dep->dev == depdev) { + list_del(&dep->node); + kfree(dep); + break; + } + + mutex_unlock(&adev->physical_node_lock); +} +EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 88eb14304667..4fdea381ef21 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -31,6 +31,7 @@ #include <linux/platform_device.h> #include <linux/jiffies.h> #include <linux/stddef.h> +#include <linux/acpi.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -309,8 +310,6 @@ static int dock_present(struct dock_station *ds) static struct acpi_device * dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; - struct acpi_device *parent_device; - acpi_handle parent; int ret; if (acpi_bus_get_device(handle, &device)) { @@ -318,16 +317,11 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) * no device created for this object, * so we should create one. */ - acpi_get_parent(handle, &parent); - if (acpi_bus_get_device(parent, &parent_device)) - parent_device = NULL; - - ret = acpi_bus_add(&device, parent_device, handle, - ACPI_BUS_TYPE_DEVICE); - if (ret) { + ret = acpi_bus_scan(handle); + if (ret) pr_debug("error adding bus, %x\n", -ret); - return NULL; - } + + acpi_bus_get_device(handle, &device); } return device; } @@ -342,13 +336,9 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) static void dock_remove_acpi_device(acpi_handle handle) { struct acpi_device *device; - int ret; - if (!acpi_bus_get_device(handle, &device)) { - ret = acpi_bus_trim(device, 1); - if (ret) - pr_debug("error removing bus, %x\n", -ret); - } + if (!acpi_bus_get_device(handle, &device)) + acpi_bus_trim(device); } /** @@ -460,12 +450,8 @@ static void handle_dock(struct dock_station *ds, int dock) struct acpi_object_list arg_list; union acpi_object arg; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - - acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); - printk(KERN_INFO PREFIX "%s - %s\n", - (char *)name_buffer.pointer, dock ? "docking" : "undocking"); + acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking"); /* _DCK method has one argument */ arg_list.count = 1; @@ -474,11 +460,10 @@ static void handle_dock(struct dock_station *ds, int dock) arg.integer.value = dock; status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute" - " _DCK\n", (char *)name_buffer.pointer)); + acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n", + status); kfree(buffer.pointer); - kfree(name_buffer.pointer); } static inline void dock(struct dock_station *ds) @@ -525,9 +510,11 @@ static void dock_lock(struct dock_station *ds, int lock) status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { if (lock) - printk(KERN_WARNING PREFIX "Locking device failed\n"); + acpi_handle_warn(ds->handle, + "Locking device failed (0x%x)\n", status); else - printk(KERN_WARNING PREFIX "Unlocking device failed\n"); + acpi_handle_warn(ds->handle, + "Unlocking device failed (0x%x)\n", status); } } @@ -667,7 +654,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) dock_lock(ds, 0); eject_dock(ds); if (dock_present(ds)) { - printk(KERN_ERR PREFIX "Unable to undock!\n"); + acpi_handle_err(ds->handle, "Unable to undock!\n"); return -EBUSY; } complete_undock(ds); @@ -715,7 +702,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) begin_dock(ds); dock(ds); if (!dock_present(ds)) { - printk(KERN_ERR PREFIX "Unable to dock!\n"); + acpi_handle_err(handle, "Unable to dock!\n"); complete_dock(ds); break; } @@ -743,7 +730,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) dock_event(ds, event, UNDOCK_EVENT); break; default: - printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); + acpi_handle_err(handle, "Unknown dock event %d\n", event); } } @@ -757,7 +744,9 @@ static void acpi_dock_deferred_cb(void *context) { struct dock_data *data = context; + acpi_scan_lock_acquire(); dock_notify(data->handle, data->event, data->ds); + acpi_scan_lock_release(); kfree(data); } @@ -770,20 +759,31 @@ static int acpi_dock_notifier_call(struct notifier_block *this, if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) return 0; + + acpi_scan_lock_acquire(); + list_for_each_entry(dock_station, &dock_stations, sibling) { if (dock_station->handle == handle) { struct dock_data *dd; + acpi_status status; dd = kmalloc(sizeof(*dd), GFP_KERNEL); if (!dd) - return 0; + break; + dd->handle = handle; dd->event = event; dd->ds = dock_station; - acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); - return 0 ; + status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, + dd); + if (ACPI_FAILURE(status)) + kfree(dd); + + break; } } + + acpi_scan_lock_release(); return 0; } @@ -838,7 +838,7 @@ static ssize_t show_docked(struct device *dev, struct dock_station *dock_station = dev->platform_data; - if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) + if (!acpi_bus_get_device(dock_station->handle, &tmp)) return snprintf(buf, PAGE_SIZE, "1\n"); return snprintf(buf, PAGE_SIZE, "0\n"); } @@ -987,7 +987,7 @@ err_rmgroup: sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group); err_unregister: platform_device_unregister(dd); - printk(KERN_ERR "%s encountered error %d\n", __func__, ret); + acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret); return ret; } @@ -1016,51 +1016,39 @@ static int dock_remove(struct dock_station *ds) } /** - * find_dock - look for a dock station + * find_dock_and_bay - look for dock stations and bays * @handle: acpi handle of a device * @lvl: unused - * @context: counter of dock stations found + * @context: unused * @rv: unused * - * This is called by acpi_walk_namespace to look for dock stations. + * This is called by acpi_walk_namespace to look for dock stations and bays. */ static __init acpi_status -find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) +find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv) { - if (is_dock(handle)) + if (is_dock(handle) || is_ejectable_bay(handle)) dock_add(handle); return AE_OK; } -static __init acpi_status -find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - /* If bay is a dock, it's already handled */ - if (is_ejectable_bay(handle) && !is_dock(handle)) - dock_add(handle); - return AE_OK; -} - static int __init dock_init(void) { if (acpi_disabled) return 0; - /* look for a dock station */ + /* look for dock stations and bays */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL); + ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL); - /* look for bay */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL); if (!dock_station_count) { - printk(KERN_INFO PREFIX "No dock devices found.\n"); + pr_info(PREFIX "No dock devices found.\n"); return 0; } register_acpi_bus_notifier(&dock_acpi_notifier); - printk(KERN_INFO PREFIX "%s: %d docks/bays found\n", + pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); return 0; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a51df9681319..d45b2871d33b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -158,10 +158,10 @@ static int ec_transaction_done(struct acpi_ec *ec) { unsigned long flags; int ret = 0; - spin_lock_irqsave(&ec->curr_lock, flags); + spin_lock_irqsave(&ec->lock, flags); if (!ec->curr || ec->curr->done) ret = 1; - spin_unlock_irqrestore(&ec->curr_lock, flags); + spin_unlock_irqrestore(&ec->lock, flags); return ret; } @@ -175,32 +175,38 @@ static void start_transaction(struct acpi_ec *ec) static void advance_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; - spin_lock_irqsave(&ec->curr_lock, flags); - if (!ec->curr) + struct transaction *t = ec->curr; + + spin_lock_irqsave(&ec->lock, flags); + if (!t) goto unlock; - if (ec->curr->wlen > ec->curr->wi) { + if (t->wlen > t->wi) { if ((status & ACPI_EC_FLAG_IBF) == 0) acpi_ec_write_data(ec, - ec->curr->wdata[ec->curr->wi++]); + t->wdata[t->wi++]); else goto err; - } else if (ec->curr->rlen > ec->curr->ri) { + } else if (t->rlen > t->ri) { if ((status & ACPI_EC_FLAG_OBF) == 1) { - ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec); - if (ec->curr->rlen == ec->curr->ri) - ec->curr->done = true; + t->rdata[t->ri++] = acpi_ec_read_data(ec); + if (t->rlen == t->ri) + t->done = true; } else goto err; - } else if (ec->curr->wlen == ec->curr->wi && + } else if (t->wlen == t->wi && (status & ACPI_EC_FLAG_IBF) == 0) - ec->curr->done = true; + t->done = true; goto unlock; err: - /* false interrupt, state didn't change */ - if (in_interrupt()) - ++ec->curr->irq_count; + /* + * If SCI bit is set, then don't think it's a false IRQ + * otherwise will take a not handled IRQ as a false one. + */ + if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI)) + ++t->irq_count; + unlock: - spin_unlock_irqrestore(&ec->curr_lock, flags); + spin_unlock_irqrestore(&ec->lock, flags); } static int acpi_ec_sync_query(struct acpi_ec *ec); @@ -238,9 +244,9 @@ static int ec_poll(struct acpi_ec *ec) if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) break; pr_debug(PREFIX "controller reset, restart transaction\n"); - spin_lock_irqsave(&ec->curr_lock, flags); + spin_lock_irqsave(&ec->lock, flags); start_transaction(ec); - spin_unlock_irqrestore(&ec->curr_lock, flags); + spin_unlock_irqrestore(&ec->lock, flags); } return -ETIME; } @@ -253,17 +259,17 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, if (EC_FLAGS_MSI) udelay(ACPI_EC_MSI_UDELAY); /* start transaction */ - spin_lock_irqsave(&ec->curr_lock, tmp); + spin_lock_irqsave(&ec->lock, tmp); /* following two actions should be kept atomic */ ec->curr = t; start_transaction(ec); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - spin_unlock_irqrestore(&ec->curr_lock, tmp); + spin_unlock_irqrestore(&ec->lock, tmp); ret = ec_poll(ec); - spin_lock_irqsave(&ec->curr_lock, tmp); + spin_lock_irqsave(&ec->lock, tmp); ec->curr = NULL; - spin_unlock_irqrestore(&ec->curr_lock, tmp); + spin_unlock_irqrestore(&ec->lock, tmp); return ret; } @@ -292,7 +298,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) return -EINVAL; if (t->rdata) memset(t->rdata, 0, t->rlen); - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) { status = -EINVAL; goto unlock; @@ -310,7 +316,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } - pr_debug(PREFIX "transaction start\n"); + pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n", + t->command, t->wdata ? t->wdata[0] : 0); /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { /* It has to be disabled, so that it doesn't trigger. */ @@ -326,8 +333,9 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ec_storm_threshold) { - pr_info(PREFIX "GPE storm detected, " - "transactions will use polling mode\n"); + pr_info(PREFIX "GPE storm detected(%d GPEs), " + "transactions will use polling mode\n", + t->irq_count); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } pr_debug(PREFIX "transaction end\n"); @@ -335,7 +343,7 @@ end: if (ec->global_lock) acpi_release_global_lock(glk); unlock: - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); return status; } @@ -403,7 +411,7 @@ int ec_burst_disable(void) EXPORT_SYMBOL(ec_burst_disable); -int ec_read(u8 addr, u8 * val) +int ec_read(u8 addr, u8 *val) { int err; u8 temp_data; @@ -468,10 +476,10 @@ void acpi_ec_block_transactions(void) if (!ec) return; - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); /* Prevent transactions from being carried out */ set_bit(EC_FLAGS_BLOCKED, &ec->flags); - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); } void acpi_ec_unblock_transactions(void) @@ -481,10 +489,10 @@ void acpi_ec_unblock_transactions(void) if (!ec) return; - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); /* Allow transactions to be carried out again */ clear_bit(EC_FLAGS_BLOCKED, &ec->flags); - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); } void acpi_ec_unblock_transactions_early(void) @@ -536,9 +544,9 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, handler->handle = handle; handler->func = func; handler->data = data; - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); list_add(&handler->node, &ec->list); - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); return 0; } @@ -547,14 +555,14 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) { struct acpi_ec_query_handler *handler, *tmp; - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); list_for_each_entry_safe(handler, tmp, &ec->list, node) { if (query_bit == handler->query_bit) { list_del(&handler->node); kfree(handler); } } - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); } EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); @@ -601,9 +609,9 @@ static void acpi_ec_gpe_query(void *ec_cxt) struct acpi_ec *ec = ec_cxt; if (!ec) return; - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); acpi_ec_sync_query(ec); - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); } static int ec_check_sci(struct acpi_ec *ec, u8 state) @@ -622,10 +630,11 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number, void *data) { struct acpi_ec *ec = data; + u8 status = acpi_ec_read_status(ec); - pr_debug(PREFIX "~~~> interrupt\n"); + pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status); - advance_transaction(ec, acpi_ec_read_status(ec)); + advance_transaction(ec, status); if (ec_transaction_done(ec) && (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { wake_up(&ec->wait); @@ -691,10 +700,10 @@ static struct acpi_ec *make_acpi_ec(void) if (!ec) return NULL; ec->flags = 1 << EC_FLAGS_QUERY_PENDING; - mutex_init(&ec->lock); + mutex_init(&ec->mutex); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); - spin_lock_init(&ec->curr_lock); + spin_lock_init(&ec->lock); return ec; } @@ -843,7 +852,7 @@ static int acpi_ec_add(struct acpi_device *device) return ret; } -static int acpi_ec_remove(struct acpi_device *device, int type) +static int acpi_ec_remove(struct acpi_device *device) { struct acpi_ec *ec; struct acpi_ec_query_handler *handler, *tmp; @@ -853,12 +862,12 @@ static int acpi_ec_remove(struct acpi_device *device, int type) ec = acpi_driver_data(device); ec_remove_handlers(ec); - mutex_lock(&ec->lock); + mutex_lock(&ec->mutex); list_for_each_entry_safe(handler, tmp, &ec->list, node) { list_del(&handler->node); kfree(handler); } - mutex_unlock(&ec->lock); + mutex_unlock(&ec->mutex); release_region(ec->data_addr, 1); release_region(ec->command_addr, 1); device->driver_data = NULL; diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 3bd6a54702d6..f815da82c765 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -45,7 +45,7 @@ MODULE_DESCRIPTION("ACPI Fan Driver"); MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); -static int acpi_fan_remove(struct acpi_device *device, int type); +static int acpi_fan_remove(struct acpi_device *device); static const struct acpi_device_id fan_device_ids[] = { {"PNP0C0B", 0}, @@ -172,7 +172,7 @@ static int acpi_fan_add(struct acpi_device *device) return result; } -static int acpi_fan_remove(struct acpi_device *device, int type) +static int acpi_fan_remove(struct acpi_device *device) { struct thermal_cooling_device *cdev = acpi_driver_data(device); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 08373086cd7e..40a84cc6740c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -18,9 +18,14 @@ #define ACPI_GLUE_DEBUG 0 #if ACPI_GLUE_DEBUG -#define DBG(x...) printk(PREFIX x) +#define DBG(fmt, ...) \ + printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__) #else -#define DBG(x...) do { } while(0) +#define DBG(fmt, ...) \ +do { \ + if (0) \ + printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__); \ +} while (0) #endif static LIST_HEAD(bus_type_list); static DECLARE_RWSEM(bus_type_sem); @@ -31,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; @@ -51,21 +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; 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; } @@ -74,102 +78,90 @@ 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; -} - -/* Get device's handler per its address under its parent */ -struct acpi_find_child { - acpi_handle handle; - u64 address; -}; - -static acpi_status -do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) +static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, + void *addr_p, void **ret_p) { + unsigned long long addr; acpi_status status; - struct acpi_device_info *info; - struct acpi_find_child *find = context; - - status = acpi_get_object_info(handle, &info); - if (ACPI_SUCCESS(status)) { - if ((info->address == find->address) - && (info->valid & ACPI_VALID_ADR)) - find->handle = handle; - kfree(info); + + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); + if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) { + *ret_p = handle; + return AE_CTRL_TERMINATE; } return AE_OK; } acpi_handle acpi_get_child(acpi_handle parent, u64 address) { - struct acpi_find_child find = { NULL, address }; + void *ret = NULL; if (!parent) return NULL; - acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, - 1, do_acpi_find_child, NULL, &find, NULL); - return find.handle; -} + acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL, + do_acpi_find_child, &address, &ret); + return (acpi_handle)ret; +} EXPORT_SYMBOL(acpi_get_child); static int acpi_bind_one(struct device *dev, acpi_handle handle) { struct acpi_device *acpi_dev; acpi_status status; - struct acpi_device_physical_node *physical_node; + struct acpi_device_physical_node *physical_node, *pn; char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2]; int retval = -EINVAL; - if (dev->archdata.acpi_handle) { - dev_warn(dev, "Drivers changed 'acpi_handle'\n"); - return -EINVAL; + if (ACPI_HANDLE(dev)) { + if (handle) { + dev_warn(dev, "ACPI handle is already set\n"); + return -EINVAL; + } else { + handle = ACPI_HANDLE(dev); + } } + if (!handle) + return -EINVAL; get_device(dev); status = acpi_bus_get_device(handle, &acpi_dev); if (ACPI_FAILURE(status)) goto err; - physical_node = kzalloc(sizeof(struct acpi_device_physical_node), - GFP_KERNEL); + physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL); if (!physical_node) { retval = -ENOMEM; goto err; } mutex_lock(&acpi_dev->physical_node_lock); + + /* Sanity check. */ + list_for_each_entry(pn, &acpi_dev->physical_node_list, node) + if (pn->dev == dev) { + dev_warn(dev, "Already associated with ACPI node\n"); + goto err_free; + } + /* allocate physical node id according to physical_node_id_bitmap */ physical_node->node_id = find_first_zero_bit(acpi_dev->physical_node_id_bitmap, ACPI_MAX_PHYSICAL_NODE); if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { retval = -ENOSPC; - mutex_unlock(&acpi_dev->physical_node_lock); - kfree(physical_node); - goto err; + goto err_free; } set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap); physical_node->dev = dev; list_add_tail(&physical_node->node, &acpi_dev->physical_node_list); acpi_dev->physical_node_count++; + mutex_unlock(&acpi_dev->physical_node_lock); - dev->archdata.acpi_handle = handle; + if (!ACPI_HANDLE(dev)) + ACPI_HANDLE_SET(dev, acpi_dev->handle); if (!physical_node->node_id) strcpy(physical_node_name, PHYSICAL_NODE_STRING); @@ -187,8 +179,14 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) return 0; err: + ACPI_HANDLE_SET(dev, NULL); put_device(dev); return retval; + + err_free: + mutex_unlock(&acpi_dev->physical_node_lock); + kfree(physical_node); + goto err; } static int acpi_unbind_one(struct device *dev) @@ -198,11 +196,10 @@ static int acpi_unbind_one(struct device *dev) acpi_status status; struct list_head *node, *next; - if (!dev->archdata.acpi_handle) + if (!ACPI_HANDLE(dev)) return 0; - status = acpi_bus_get_device(dev->archdata.acpi_handle, - &acpi_dev); + status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev); if (ACPI_FAILURE(status)) goto err; @@ -228,7 +225,7 @@ static int acpi_unbind_one(struct device *dev) sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name); sysfs_remove_link(&dev->kobj, "firmware_node"); - dev->archdata.acpi_handle = NULL; + ACPI_HANDLE_SET(dev, NULL); /* acpi_bind_one increase refcnt by one */ put_device(dev); kfree(entry); @@ -244,33 +241,31 @@ err: 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 = -EINVAL; - - if (!dev->bus || !dev->parent) { - /* bridge devices genernally haven't bus or parent */ - ret = acpi_find_bridge_device(dev, &handle); - goto end; - } - type = acpi_get_bus_type(dev->bus); - if (!type) { - DBG("No ACPI bus support for %s\n", dev_name(dev)); - ret = -EINVAL; - goto end; + int ret; + + ret = acpi_bind_one(dev, NULL); + if (ret && type) { + ret = type->find_device(dev, &handle); + if (ret) { + DBG("Unable to get handle for %s\n", dev_name(dev)); + goto out; + } + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; } - if ((ret = type->find_device(dev, &handle)) != 0) - DBG("Can't get handler for %s\n", dev_name(dev)); - end: - if (!ret) - acpi_bind_one(dev, handle); + if (type && type->setup) + type->setup(dev); + + out: #if ACPI_GLUE_DEBUG if (!ret) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_get_name(dev->archdata.acpi_handle, - ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); kfree(buffer.pointer); } else @@ -282,6 +277,12 @@ static int acpi_platform_notify(struct device *dev) static int acpi_platform_notify_remove(struct device *dev) { + struct acpi_bus_type *type; + + type = acpi_get_bus_type(dev); + if (type && type->cleanup) + type->cleanup(dev); + acpi_unbind_one(dev); return 0; } diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index 20a0f2c3ca3b..13b1d39d7cdf 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -61,7 +61,7 @@ static void acpi_hed_notify(struct acpi_device *device, u32 event) blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL); } -static int __devinit acpi_hed_add(struct acpi_device *device) +static int acpi_hed_add(struct acpi_device *device) { /* Only one hardware error device */ if (hed_handle) @@ -70,7 +70,7 @@ static int __devinit acpi_hed_add(struct acpi_device *device) return 0; } -static int __devexit acpi_hed_remove(struct acpi_device *device, int type) +static int acpi_hed_remove(struct acpi_device *device) { hed_handle = NULL; return 0; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ca75b9ce0489..3c94a732b4b3 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -25,7 +25,22 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); +#ifdef CONFIG_ACPI_PCI_SLOT +void acpi_pci_slot_init(void); +#else +static inline void acpi_pci_slot_init(void) { } +#endif +void acpi_pci_root_init(void); +void acpi_pci_link_init(void); +void acpi_pci_root_hp_init(void); +void acpi_platform_init(void); int acpi_sysfs_init(void); +void acpi_csrt_init(void); +#ifdef CONFIG_ACPI_CONTAINER +void acpi_container_init(void); +#else +static inline void acpi_container_init(void) {} +#endif #ifdef CONFIG_DEBUG_FS extern struct dentry *acpi_debugfs_dir; @@ -35,15 +50,33 @@ static inline void acpi_debugfs_init(void) { return; } #endif /* -------------------------------------------------------------------------- + Device Node Initialization / Removal + -------------------------------------------------------------------------- */ +#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ + ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) + +int acpi_device_add(struct acpi_device *device, + void (*release)(struct device *)); +void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, + int type, unsigned long long sta); +void acpi_device_add_finalize(struct acpi_device *device); +void acpi_free_ids(struct acpi_device *device); + +/* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ int acpi_power_init(void); +void acpi_power_resources_list_free(struct list_head *list); +int acpi_extract_power_resources(union acpi_object *package, unsigned int start, + struct list_head *list); +int acpi_add_power_resource(acpi_handle handle); +void acpi_power_add_remove_device(struct acpi_device *adev, bool add); +int acpi_power_wakeup_list_init(struct list_head *list, int *system_level); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); int acpi_power_get_inferred_state(struct acpi_device *device, int *state); int acpi_power_on_resources(struct acpi_device *device, int state); int acpi_power_transition(struct acpi_device *device, int state); -int acpi_bus_init_power(struct acpi_device *device); int acpi_wakeup_device_init(void); void acpi_early_processor_set_pdc(void); @@ -58,11 +91,11 @@ struct acpi_ec { unsigned long data_addr; unsigned long global_lock; unsigned long flags; - struct mutex lock; + struct mutex mutex; wait_queue_head_t wait; struct list_head list; struct transaction *curr; - spinlock_t curr_lock; + spinlock_t lock; }; extern struct acpi_ec *first_ec; @@ -93,4 +126,9 @@ static inline int suspend_nvs_save(void) { return 0; } static inline void suspend_nvs_restore(void) {} #endif +/*-------------------------------------------------------------------------- + Platform bus support + -------------------------------------------------------------------------- */ +struct platform_device; + #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index cb31298ca684..33e609f63585 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -116,14 +116,16 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) struct acpi_srat_mem_affinity *p = (struct acpi_srat_mem_affinity *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s\n", + "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", (unsigned long)p->base_address, (unsigned long)p->length, p->proximity_domain, (p->flags & ACPI_SRAT_MEM_ENABLED)? "enabled" : "disabled", (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? - " hot-pluggable" : "")); + " hot-pluggable" : "", + (p->flags & ACPI_SRAT_MEM_NON_VOLATILE)? + " non-volatile" : "")); } #endif /* ACPI_DEBUG_OUTPUT */ break; @@ -273,7 +275,7 @@ static int __init acpi_parse_srat(struct acpi_table_header *table) static int __init acpi_table_parse_srat(enum acpi_srat_type id, - acpi_table_entry_handler handler, unsigned int max_entries) + acpi_tbl_entry_handler handler, unsigned int max_entries) { return acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat), id, diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 9eaf708f5885..586e7e993d3d 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -84,8 +84,7 @@ static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; static struct workqueue_struct *kacpi_notify_wq; -struct workqueue_struct *kacpi_hotplug_wq; -EXPORT_SYMBOL(kacpi_hotplug_wq); +static struct workqueue_struct *kacpi_hotplug_wq; /* * This list of permanent mappings is for memory that may be accessed from @@ -250,7 +249,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) return acpi_rsdp; #endif - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) return efi.acpi20; else if (efi.acpi != EFI_INVALID_TABLE_ADDR) @@ -534,6 +533,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val, return AE_OK; } +#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE +#include <linux/earlycpio.h> +#include <linux/memblock.h> + +static u64 acpi_tables_addr; +static int all_tables_size; + +/* Copied from acpica/tbutils.c:acpi_tb_checksum() */ +u8 __init acpi_table_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) + sum = (u8) (sum + *(buffer++)); + return sum; +} + +/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */ +static const char * const table_sigs[] = { + ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ, + ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT, + ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF, + ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET, + ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI, + ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA, + ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, + ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, + ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; + +/* Non-fatal errors: Affected tables/files are ignored */ +#define INVALID_TABLE(x, path, name) \ + { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; } + +#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) + +/* Must not increase 10 or needs code modification below */ +#define ACPI_OVERRIDE_TABLES 10 + +void __init acpi_initrd_override(void *data, size_t size) +{ + int sig, no, table_nr = 0, total_offset = 0; + long offset = 0; + struct acpi_table_header *table; + char cpio_path[32] = "kernel/firmware/acpi/"; + struct cpio_data file; + struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES]; + char *p; + + if (data == NULL || size == 0) + return; + + for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) { + file = find_cpio_data(cpio_path, data, size, &offset); + if (!file.data) + break; + + data += offset; + size -= offset; + + if (file.size < sizeof(struct acpi_table_header)) + INVALID_TABLE("Table smaller than ACPI header", + cpio_path, file.name); + + table = file.data; + + for (sig = 0; table_sigs[sig]; sig++) + if (!memcmp(table->signature, table_sigs[sig], 4)) + break; + + if (!table_sigs[sig]) + INVALID_TABLE("Unknown signature", + cpio_path, file.name); + if (file.size != table->length) + INVALID_TABLE("File length does not match table length", + cpio_path, file.name); + if (acpi_table_checksum(file.data, table->length)) + INVALID_TABLE("Bad table checksum", + cpio_path, file.name); + + pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n", + table->signature, cpio_path, file.name, table->length); + + all_tables_size += table->length; + early_initrd_files[table_nr].data = file.data; + early_initrd_files[table_nr].size = file.size; + table_nr++; + } + if (table_nr == 0) + return; + + acpi_tables_addr = + memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT, + all_tables_size, PAGE_SIZE); + if (!acpi_tables_addr) { + WARN_ON(1); + return; + } + /* + * Only calling e820_add_reserve does not work and the + * tables are invalid (memory got used) later. + * memblock_reserve works as expected and the tables won't get modified. + * But it's not enough on X86 because ioremap will + * complain later (used by acpi_os_map_memory) that the pages + * that should get mapped are not marked "reserved". + * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) + * works fine. + */ + memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size); + arch_reserve_mem_area(acpi_tables_addr, all_tables_size); + + p = early_ioremap(acpi_tables_addr, all_tables_size); + + for (no = 0; no < table_nr; no++) { + memcpy(p + total_offset, early_initrd_files[no].data, + early_initrd_files[no].size); + total_offset += early_initrd_files[no].size; + } + early_iounmap(p, all_tables_size); +} +#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ + +static void acpi_table_taint(struct acpi_table_header *table) +{ + pr_warn(PREFIX + "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n", + table->signature, table->oem_table_id); + add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); +} + + acpi_status acpi_os_table_override(struct acpi_table_header * existing_table, struct acpi_table_header ** new_table) @@ -547,24 +677,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table, if (strncmp(existing_table->signature, "DSDT", 4) == 0) *new_table = (struct acpi_table_header *)AmlCode; #endif - if (*new_table != NULL) { - printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], " - "this is unsafe: tainting kernel\n", - existing_table->signature, - existing_table->oem_table_id); - add_taint(TAINT_OVERRIDDEN_ACPI_TABLE); - } + if (*new_table != NULL) + acpi_table_taint(existing_table); return AE_OK; } acpi_status acpi_os_physical_table_override(struct acpi_table_header *existing_table, - acpi_physical_address * new_address, - u32 *new_table_length) + acpi_physical_address *address, + u32 *table_length) { - return AE_SUPPORT; -} +#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE + *table_length = 0; + *address = 0; + return AE_OK; +#else + int table_offset = 0; + struct acpi_table_header *table; + + *table_length = 0; + *address = 0; + + if (!acpi_tables_addr) + return AE_OK; + + do { + if (table_offset + ACPI_HEADER_SIZE > all_tables_size) { + WARN_ON(1); + return AE_OK; + } + table = acpi_os_map_memory(acpi_tables_addr + table_offset, + ACPI_HEADER_SIZE); + + if (table_offset + table->length > all_tables_size) { + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + WARN_ON(1); + return AE_OK; + } + + table_offset += table->length; + + if (memcmp(existing_table->signature, table->signature, 4)) { + acpi_os_unmap_memory(table, + ACPI_HEADER_SIZE); + continue; + } + + /* Only override tables with matching oem id */ + if (memcmp(table->oem_table_id, existing_table->oem_table_id, + ACPI_OEM_TABLE_ID_SIZE)) { + acpi_os_unmap_memory(table, + ACPI_HEADER_SIZE); + continue; + } + + table_offset -= table->length; + *table_length = table->length; + acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); + *address = acpi_tables_addr + table_offset; + break; + } while (table_offset + ACPI_HEADER_SIZE < all_tables_size); + + if (*address != 0) + acpi_table_taint(existing_table); + return AE_OK; +#endif +} static irqreturn_t acpi_irq(int irq, void *dev_id) { @@ -607,7 +786,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_handler = handler; acpi_irq_context = context; - if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { + if (request_irq(irq, acpi_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; @@ -932,7 +1111,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, * having a static work_struct. */ - dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); + dpc = kzalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); if (!dpc) return AE_NO_MEMORY; @@ -944,17 +1123,22 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, * because the hotplug code may call driver .remove() functions, * which invoke flush_scheduled_work/acpi_os_wait_events_complete * to flush these workqueues. + * + * To prevent lockdep from complaining unnecessarily, make sure that + * there is a different static lockdep key for each workqueue by using + * INIT_WORK() for each of them separately. */ - queue = hp ? kacpi_hotplug_wq : - (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); - dpc->wait = hp ? 1 : 0; - - if (queue == kacpi_hotplug_wq) + if (hp) { + queue = kacpi_hotplug_wq; + dpc->wait = 1; INIT_WORK(&dpc->work, acpi_os_execute_deferred); - else if (queue == kacpi_notify_wq) + } else if (type == OSL_NOTIFY_HANDLER) { + queue = kacpi_notify_wq; INIT_WORK(&dpc->work, acpi_os_execute_deferred); - else + } else { + queue = kacpid_wq; INIT_WORK(&dpc->work, acpi_os_execute_deferred); + } /* * On some machines, a software-initiated SMI causes corruption unless @@ -986,6 +1170,7 @@ acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function, { return __acpi_os_execute(0, function, context, 1); } +EXPORT_SYMBOL(acpi_os_hotplug_execute); void acpi_os_wait_events_complete(void) { @@ -1592,3 +1777,24 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, { __acpi_os_prepare_sleep = func; } + +void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, + void (*func)(struct work_struct *work)) +{ + struct acpi_hp_work *hp_work; + int ret; + + hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); + if (!hp_work) + return; + + hp_work->handle = handle; + hp_work->type = type; + hp_work->context = context; + + INIT_WORK(&hp_work->work, func); + ret = queue_work(kacpi_hotplug_wq, &hp_work->work); + if (!ret) + kfree(hp_work); +} +EXPORT_SYMBOL_GPL(alloc_acpi_hp_work); diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c deleted file mode 100644 index 2ef04098cc1d..000000000000 --- a/drivers/acpi/pci_bind.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $) - * - * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> - * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/pci-acpi.h> -#include <linux/acpi.h> -#include <linux/pm_runtime.h> -#include <acpi/acpi_bus.h> -#include <acpi/acpi_drivers.h> - -#define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_bind"); - -static int acpi_pci_unbind(struct acpi_device *device) -{ - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - goto out; - - device_set_run_wake(&dev->dev, false); - pci_acpi_remove_pm_notifier(device); - - if (!dev->subordinate) - goto out; - - acpi_pci_irq_del_prt(dev->subordinate); - - device->ops.bind = NULL; - device->ops.unbind = NULL; - -out: - pci_dev_put(dev); - return 0; -} - -static int acpi_pci_bind(struct acpi_device *device) -{ - acpi_status status; - acpi_handle handle; - struct pci_bus *bus; - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - return 0; - - pci_acpi_add_pm_notifier(device, dev); - if (device->wakeup.flags.run_wake) - device_set_run_wake(&dev->dev, true); - - /* - * Install the 'bind' function to facilitate callbacks for - * children of the P2P bridge. - */ - if (dev->subordinate) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %04x:%02x:%02x.%d is a PCI bridge\n", - pci_domain_nr(dev->bus), dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - } - - /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that - * _PRTs within the scope of a PCI bridge assume the bridge's - * subordinate bus number. - * - * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? - */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_FAILURE(status)) - goto out; - - if (dev->subordinate) - bus = dev->subordinate; - else - bus = dev->bus; - - acpi_pci_irq_add_prt(device->handle, bus); - -out: - pci_dev_put(dev); - return 0; -} - -int acpi_pci_bind_root(struct acpi_device *device) -{ - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - - return 0; -} diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 0eefa12e648c..41c5e1b799ef 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -53,9 +53,6 @@ struct acpi_prt_entry { u32 index; /* GSI, or link _CRS index */ }; -static LIST_HEAD(acpi_prt_list); -static DEFINE_SPINLOCK(acpi_prt_lock); - static inline char pin_name(int pin) { return 'A' + pin - 1; @@ -65,28 +62,6 @@ static inline char pin_name(int pin) PCI IRQ Routing Table (PRT) Support -------------------------------------------------------------------------- */ -static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, - int pin) -{ - struct acpi_prt_entry *entry; - int segment = pci_domain_nr(dev->bus); - int bus = dev->bus->number; - int device = PCI_SLOT(dev->devfn); - - spin_lock(&acpi_prt_lock); - list_for_each_entry(entry, &acpi_prt_list, list) { - if ((segment == entry->id.segment) - && (bus == entry->id.bus) - && (device == entry->id.device) - && (pin == entry->pin)) { - spin_unlock(&acpi_prt_lock); - return entry; - } - } - spin_unlock(&acpi_prt_lock); - return NULL; -} - /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ static const struct dmi_system_id medion_md9580[] = { { @@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, } } -static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, - struct acpi_pci_routing_table *prt) +static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev, + int pin, struct acpi_pci_routing_table *prt, + struct acpi_prt_entry **entry_ptr) { + int segment = pci_domain_nr(dev->bus); + int bus = dev->bus->number; + int device = PCI_SLOT(dev->devfn); struct acpi_prt_entry *entry; + if (((prt->address >> 16) & 0xffff) != device || + prt->pin + 1 != pin) + return -ENODEV; + entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); if (!entry) return -ENOMEM; @@ -198,8 +181,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert * it here. */ - entry->id.segment = pci_domain_nr(bus); - entry->id.bus = bus->number; + entry->id.segment = segment; + entry->id.bus = bus; entry->id.device = (prt->address >> 16) & 0xFFFF; entry->pin = prt->pin + 1; @@ -237,43 +220,37 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, entry->id.device, pin_name(entry->pin), prt->source, entry->index)); - spin_lock(&acpi_prt_lock); - list_add_tail(&entry->list, &acpi_prt_list); - spin_unlock(&acpi_prt_lock); + *entry_ptr = entry; return 0; } -int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) +static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev, + int pin, struct acpi_prt_entry **entry_ptr) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_pci_routing_table *entry; + acpi_handle handle = NULL; - /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ - status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - if (ACPI_FAILURE(status)) - return -ENODEV; - - printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", - (char *) buffer.pointer); + if (dev->bus->bridge) + handle = ACPI_HANDLE(dev->bus->bridge); - kfree(buffer.pointer); - - buffer.length = ACPI_ALLOCATE_BUFFER; - buffer.pointer = NULL; + if (!handle) + return -ENODEV; + /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ status = acpi_get_irq_routing_table(handle, &buffer); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", - acpi_format_exception(status))); kfree(buffer.pointer); return -ENODEV; } entry = buffer.pointer; while (entry && (entry->length > 0)) { - acpi_pci_irq_add_entry(handle, bus, entry); + if (!acpi_pci_irq_check_entry(handle, dev, pin, + entry, entry_ptr)) + break; entry = (struct acpi_pci_routing_table *) ((unsigned long)entry + entry->length); } @@ -282,24 +259,6 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) return 0; } -void acpi_pci_irq_del_prt(struct pci_bus *bus) -{ - struct acpi_prt_entry *entry, *tmp; - - printk(KERN_DEBUG - "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", - pci_domain_nr(bus), bus->number); - spin_lock(&acpi_prt_lock); - list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { - if (pci_domain_nr(bus) == entry->id.segment - && bus->number == entry->id.bus) { - list_del(&entry->list); - kfree(entry); - } - } - spin_unlock(&acpi_prt_lock); -} - /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ @@ -360,12 +319,13 @@ static int acpi_reroute_boot_interrupt(struct pci_dev *dev, static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { - struct acpi_prt_entry *entry; + struct acpi_prt_entry *entry = NULL; struct pci_dev *bridge; u8 bridge_pin, orig_pin = pin; + int ret; - entry = acpi_pci_irq_find_prt_entry(dev, pin); - if (entry) { + ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry); + if (!ret && entry) { #ifdef CONFIG_X86_IO_APIC acpi_reroute_boot_interrupt(dev, entry); #endif /* CONFIG_X86_IO_APIC */ @@ -374,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) return entry; } - /* + /* * Attempt to derive an IRQ for this device from a parent bridge's * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). */ @@ -394,8 +354,8 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) pin = bridge_pin; } - entry = acpi_pci_irq_find_prt_entry(bridge, pin); - if (entry) { + ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry); + if (!ret && entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI for %s INT %c from %s\n", pci_name(dev), pin_name(orig_pin), @@ -459,25 +419,27 @@ int acpi_pci_irq_enable(struct pci_dev *dev) */ if (gsi < 0) { u32 dev_gsi; - dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq > 0 && (dev->irq <= 0xF) && (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { - printk(" - using ISA IRQ %d\n", dev->irq); + dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n", + pin_name(pin), dev->irq); acpi_register_gsi(&dev->dev, dev_gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); - return 0; } else { - printk("\n"); - return 0; + dev_warn(&dev->dev, "PCI INT %c: no GSI\n", + pin_name(pin)); } + + return 0; } rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity); if (rc < 0) { dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", pin_name(pin)); + kfree(entry); return rc; } dev->irq = rc; @@ -492,14 +454,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev) (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); + kfree(entry); return 0; } -/* FIXME: implement x86/x86_64 version */ -void __attribute__ ((weak)) acpi_unregister_gsi(u32 i) -{ -} - void acpi_pci_irq_disable(struct pci_dev *dev) { struct acpi_prt_entry *entry; @@ -519,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev) else gsi = entry->index; + kfree(entry); + /* * TBD: It might be worth clearing dev->irq by magic constant * (e.g. PCI_UNDEFINED_IRQ). diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index a12808259dfb..ab764ed34a50 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_FILE_STATUS "state" #define ACPI_PCI_LINK_MAX_POSSIBLE 16 -static int acpi_pci_link_add(struct acpi_device *device); -static int acpi_pci_link_remove(struct acpi_device *device, int type); +static int acpi_pci_link_add(struct acpi_device *device, + const struct acpi_device_id *not_used); +static void acpi_pci_link_remove(struct acpi_device *device); static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, link_device_ids); -static struct acpi_driver acpi_pci_link_driver = { - .name = "pci_link", - .class = ACPI_PCI_LINK_CLASS, +static struct acpi_scan_handler pci_link_handler = { .ids = link_device_ids, - .ops = { - .add = acpi_pci_link_add, - .remove = acpi_pci_link_remove, - }, + .attach = acpi_pci_link_add, + .detach = acpi_pci_link_remove, }; /* @@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle handle) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_pci_link_add(struct acpi_device *device) +static int acpi_pci_link_add(struct acpi_device *device, + const struct acpi_device_id *not_used) { int result; struct acpi_pci_link *link; @@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi_device *device) if (result) kfree(link); - return result; + return result < 0 ? result : 1; } static int acpi_pci_link_resume(struct acpi_pci_link *link) @@ -766,7 +763,7 @@ static void irqrouter_resume(void) } } -static int acpi_pci_link_remove(struct acpi_device *device, int type) +static void acpi_pci_link_remove(struct acpi_device *device) { struct acpi_pci_link *link; @@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) mutex_unlock(&acpi_link_lock); kfree(link); - return 0; } /* @@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_syscore_ops = { .resume = irqrouter_resume, }; -static int __init irqrouter_init_ops(void) -{ - if (!acpi_disabled && !acpi_noirq) - register_syscore_ops(&irqrouter_syscore_ops); - - return 0; -} - -device_initcall(irqrouter_init_ops); - -static int __init acpi_pci_link_init(void) +void __init acpi_pci_link_init(void) { if (acpi_noirq) - return 0; + return; if (acpi_irq_balance == -1) { /* no command line switch: enable balancing in IOAPIC mode */ @@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(void) else acpi_irq_balance = 0; } - - if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) - return -ENODEV; - - return 0; + register_syscore_ops(&irqrouter_syscore_ops); + acpi_scan_add_handler(&pci_link_handler); } - -subsys_initcall(acpi_pci_link_init); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index bce469c0b48a..0ac546d5e53f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -45,9 +45,9 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" -static int acpi_pci_root_add(struct acpi_device *device); -static int acpi_pci_root_remove(struct acpi_device *device, int type); -static int acpi_pci_root_start(struct acpi_device *device); +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used); +static void acpi_pci_root_remove(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -58,17 +58,11 @@ static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, root_device_ids); -static struct acpi_driver acpi_pci_root_driver = { - .name = "pci_root", - .class = ACPI_PCI_ROOT_CLASS, +static struct acpi_scan_handler pci_root_handler = { .ids = root_device_ids, - .ops = { - .add = acpi_pci_root_add, - .remove = acpi_pci_root_remove, - .start = acpi_pci_root_start, - }, + .attach = acpi_pci_root_add, + .detach = acpi_pci_root_remove, }; /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ @@ -109,24 +103,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) } 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)) { - handle = root->device->handle; - break; - } - mutex_unlock(&acpi_pci_root_lock); - return handle; -} - -EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); - /** * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge * @handle - the ACPI CA node in question. @@ -188,21 +164,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle, return AE_OK; } -static void acpi_pci_bridge_scan(struct acpi_device *device) -{ - int status; - struct acpi_device *child = NULL; - - if (device->flags.bus_address) - if (device->parent && device->parent->ops.bind) { - status = device->parent->ops.bind(device); - if (!status) { - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - } - } -} - static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, @@ -445,15 +406,16 @@ out: } EXPORT_SYMBOL(acpi_pci_osc_control_set); -static int __devinit acpi_pci_root_add(struct acpi_device *device) +static int acpi_pci_root_add(struct acpi_device *device, + const struct acpi_device_id *not_used) { unsigned long long segment, bus; acpi_status status; int result; struct acpi_pci_root *root; - acpi_handle handle; - struct acpi_device *child; + struct acpi_pci_driver *driver; u32 flags, base_flags; + bool is_osc_granted = false; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -501,6 +463,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); device->driver_data = root; + printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", + acpi_device_name(device), acpi_device_bid(device), + root->segment, &root->secondary); + root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); /* @@ -510,76 +476,24 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; acpi_pci_osc_support(root, flags); - /* - * TBD: Need PCI interface for enumeration/configuration of roots. - */ - - 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), - root->segment, &root->secondary); - - /* - * Scan the Root Bridge - * -------------------- - * Must do this prior to any attempt to bind the root device, as the - * PCI namespace does not get created until this call is made (and - * thus the root bridge's pci_dev does not exist). - */ - root->bus = pci_acpi_scan_root(root); - if (!root->bus) { - printk(KERN_ERR PREFIX - "Bus %04x:%02x not present in PCI namespace\n", - root->segment, (unsigned int)root->secondary.start); - result = -ENODEV; - goto out_del_root; - } - - /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - result = acpi_pci_bind_root(device); - if (result) - goto out_del_root; - - /* - * PCI Routing Table - * ----------------- - * Evaluate and parse _PRT, if exists. - */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_SUCCESS(status)) - result = acpi_pci_irq_add_prt(device->handle, root->bus); - - /* - * Scan and bind all _ADR-Based Devices - */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - /* Indicate support for various _OSC capabilities. */ - if (pci_ext_cfg_avail(root->bus->self)) + if (pci_ext_cfg_avail()) flags |= OSC_EXT_PCI_CONFIG_SUPPORT; - if (pcie_aspm_support_enabled()) + if (pcie_aspm_support_enabled()) { flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + } if (pci_msi_enabled()) flags |= OSC_MSI_SUPPORT; if (flags != base_flags) { status = acpi_pci_osc_support(root, flags); if (ACPI_FAILURE(status)) { - dev_info(root->bus->bridge, "ACPI _OSC support " + dev_info(&device->dev, "ACPI _OSC support " "notification failed, disabling PCIe ASPM\n"); pcie_no_aspm(); flags = base_flags; } } - if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL @@ -588,61 +502,76 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (pci_aer_available()) { if (aer_acpi_firmware_first()) - dev_dbg(root->bus->bridge, + dev_dbg(&device->dev, "PCIe errors handled by BIOS.\n"); else flags |= OSC_PCI_EXPRESS_AER_CONTROL; } - dev_info(root->bus->bridge, + dev_info(&device->dev, "Requesting ACPI _OSC control (0x%02x)\n", flags); status = acpi_pci_osc_control_set(device->handle, &flags, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); if (ACPI_SUCCESS(status)) { - dev_info(root->bus->bridge, + is_osc_granted = true; + dev_info(&device->dev, "ACPI _OSC control (0x%02x) granted\n", flags); - if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { - /* - * We have ASPM control, but the FADT indicates - * that it's unsupported. Clear it. - */ - pcie_clear_aspm(root->bus); - } } else { - dev_info(root->bus->bridge, + is_osc_granted = false; + dev_info(&device->dev, "ACPI _OSC request failed (%s), " "returned control mask: 0x%02x\n", acpi_format_exception(status), flags); - pr_info("ACPI _OSC control for PCIe not granted, " - "disabling ASPM\n"); - pcie_no_aspm(); } } else { - dev_info(root->bus->bridge, - "Unable to request _OSC control " - "(_OSC support mask: 0x%02x)\n", flags); + dev_info(&device->dev, + "Unable to request _OSC control " + "(_OSC support mask: 0x%02x)\n", flags); } - pci_acpi_add_bus_pm_notifier(device, root->bus); - if (device->wakeup.flags.run_wake) - device_set_run_wake(root->bus->bridge, true); - - return 0; + /* + * TBD: Need PCI interface for enumeration/configuration of roots. + */ -out_del_root: mutex_lock(&acpi_pci_root_lock); - list_del(&root->node); + list_add_tail(&root->node, &acpi_pci_roots); mutex_unlock(&acpi_pci_root_lock); -end: - kfree(root); - return result; -} -static int acpi_pci_root_start(struct acpi_device *device) -{ - struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; + /* + * Scan the Root Bridge + * -------------------- + * Must do this prior to any attempt to bind the root device, as the + * PCI namespace does not get created until this call is made (and + * thus the root bridge's pci_dev does not exist). + */ + root->bus = pci_acpi_scan_root(root); + if (!root->bus) { + printk(KERN_ERR PREFIX + "Bus %04x:%02x not present in PCI namespace\n", + root->segment, (unsigned int)root->secondary.start); + result = -ENODEV; + goto out_del_root; + } + + /* ASPM setting */ + if (is_osc_granted) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) + pcie_clear_aspm(root->bus); + } else { + pr_info("ACPI _OSC control for PCIe not granted, " + "disabling ASPM\n"); + pcie_no_aspm(); + } + + pci_acpi_add_bus_pm_notifier(device, root->bus); + if (device->wakeup.flags.run_wake) + device_set_run_wake(root->bus->bridge, true); + + if (system_state != SYSTEM_BOOTING) { + pcibios_resource_survey_bus(root->bus); + pci_assign_unassigned_bus_resources(root->bus); + } mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) @@ -650,42 +579,183 @@ static int acpi_pci_root_start(struct acpi_device *device) driver->add(root); mutex_unlock(&acpi_pci_root_lock); + /* need to after hot-added ioapic is registered */ + if (system_state != SYSTEM_BOOTING) + pci_enable_bridges(root->bus); + pci_bus_add_devices(root->bus); + return 1; + +out_del_root: + mutex_lock(&acpi_pci_root_lock); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); - return 0; +end: + kfree(root); + return result; } -static int acpi_pci_root_remove(struct acpi_device *device, int type) +static void acpi_pci_root_remove(struct acpi_device *device) { struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + pci_stop_root_bus(root->bus); + mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) + list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) if (driver->remove) driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); + pci_remove_root_bus(root->bus); + + mutex_lock(&acpi_pci_root_lock); list_del(&root->node); mutex_unlock(&acpi_pci_root_lock); kfree(root); - return 0; } -static int __init acpi_pci_root_init(void) +void __init acpi_pci_root_init(void) { acpi_hest_init(); - if (acpi_pci_disabled) - return 0; + if (!acpi_pci_disabled) { + pci_acpi_crs_quirks(); + acpi_scan_add_handler(&pci_root_handler); + } +} +/* Support root bridge hotplug */ + +static void handle_root_bridge_insertion(acpi_handle handle) +{ + struct acpi_device *device; + + if (!acpi_bus_get_device(handle, &device)) { + printk(KERN_DEBUG "acpi device exists...\n"); + return; + } + + if (acpi_bus_scan(handle)) + printk(KERN_ERR "cannot add bridge to acpi list\n"); +} + +static void handle_root_bridge_removal(struct acpi_device *device) +{ + struct acpi_eject_event *ej_event; + + ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); + if (!ej_event) { + /* Inform firmware the hot-remove operation has error */ + (void) acpi_evaluate_hotplug_ost(device->handle, + ACPI_NOTIFY_EJECT_REQUEST, + ACPI_OST_SC_NON_SPECIFIC_FAILURE, + NULL); + return; + } + + ej_event->device = device; + ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + + acpi_bus_hot_remove_device(ej_event); +} + +static void _handle_hotplug_event_root(struct work_struct *work) +{ + struct acpi_pci_root *root; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; + struct acpi_hp_work *hp_work; + acpi_handle handle; + u32 type; + + hp_work = container_of(work, struct acpi_hp_work, work); + handle = hp_work->handle; + type = hp_work->type; + + root = acpi_pci_find_root(handle); + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + /* bus enumerate */ + printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, + (char *)buffer.pointer); + if (!root) + handle_root_bridge_insertion(handle); + + break; + + case ACPI_NOTIFY_DEVICE_CHECK: + /* device check */ + printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__, + (char *)buffer.pointer); + if (!root) + handle_root_bridge_insertion(handle); + break; + + case ACPI_NOTIFY_EJECT_REQUEST: + /* request device eject */ + printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__, + (char *)buffer.pointer); + if (root) + handle_root_bridge_removal(root->device); + break; + default: + printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n", + type, (char *)buffer.pointer); + break; + } + + kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ + kfree(buffer.pointer); +} + +static void handle_hotplug_event_root(acpi_handle handle, u32 type, + void *context) +{ + alloc_acpi_hp_work(handle, type, context, + _handle_hotplug_event_root); +} + +static acpi_status __init +find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + char objname[64]; + struct acpi_buffer buffer = { .length = sizeof(objname), + .pointer = objname }; + int *count = (int *)context; + + if (!acpi_is_root_bridge(handle)) + return AE_OK; + + (*count)++; + + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - pci_acpi_crs_quirks(); - if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) - return -ENODEV; + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_root, NULL); + if (ACPI_FAILURE(status)) + printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n", + objname, (unsigned int)status); + else + printk(KERN_DEBUG "acpi root: %s notify handler is installed\n", + objname); - return 0; + return AE_OK; } -subsys_initcall(acpi_pci_root_init); +void __init acpi_pci_root_hp_init(void) +{ + int num = 0; + + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); + + printk(KERN_DEBUG "Found %d acpi root devices\n", num); +} diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index d22585f21aeb..cd1434eb1de8 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -50,13 +50,12 @@ module_param(debug, bool, 0644); ACPI_MODULE_NAME("pci_slot"); #define MY_NAME "pci_slot" -#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) +#define err(format, arg...) pr_err("%s: " format , MY_NAME , ## arg) +#define info(format, arg...) pr_info("%s: " format , MY_NAME , ## arg) #define dbg(format, arg...) \ do { \ if (debug) \ - printk(KERN_DEBUG "%s: " format, \ - MY_NAME , ## arg); \ + pr_debug("%s: " format, MY_NAME , ## arg); \ } while (0) #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ @@ -330,19 +329,8 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = { {} }; -static int __init -acpi_pci_slot_init(void) +void __init acpi_pci_slot_init(void) { dmi_check_system(acpi_pci_slot_dmi_table); acpi_pci_register_driver(&acpi_pci_slot_driver); - return 0; } - -static void __exit -acpi_pci_slot_exit(void) -{ - acpi_pci_unregister_driver(&acpi_pci_slot_driver); -} - -module_init(acpi_pci_slot_init); -module_exit(acpi_pci_slot_exit); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 40e38a06ba85..34f5ef11d427 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -41,6 +41,7 @@ #include <linux/types.h> #include <linux/slab.h> #include <linux/pm_runtime.h> +#include <linux/sysfs.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include "sleep.h" @@ -58,88 +59,122 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -static int acpi_power_add(struct acpi_device *device); -static int acpi_power_remove(struct acpi_device *device, int type); - -static const struct acpi_device_id power_device_ids[] = { - {ACPI_POWER_HID, 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, power_device_ids); - -#ifdef CONFIG_PM_SLEEP -static int acpi_power_resume(struct device *dev); -#endif -static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume); - -static struct acpi_driver acpi_power_driver = { - .name = "power", - .class = ACPI_POWER_CLASS, - .ids = power_device_ids, - .ops = { - .add = acpi_power_add, - .remove = acpi_power_remove, - }, - .drv.pm = &acpi_power_pm, -}; - -/* - * A power managed device - * A device may rely on multiple power resources. - * */ -struct acpi_power_managed_device { - struct device *dev; /* The physical device */ - acpi_handle *handle; -}; - -struct acpi_power_resource_device { - struct acpi_power_managed_device *device; - struct acpi_power_resource_device *next; +struct acpi_power_dependent_device { + struct list_head node; + struct acpi_device *adev; + struct work_struct work; }; struct acpi_power_resource { - struct acpi_device * device; - acpi_bus_id name; + struct acpi_device device; + struct list_head list_node; + struct list_head dependent; + char *name; u32 system_level; u32 order; unsigned int ref_count; + bool wakeup_enabled; struct mutex resource_lock; +}; - /* List of devices relying on this power resource */ - struct acpi_power_resource_device *devices; - struct mutex devices_lock; +struct acpi_power_resource_entry { + struct list_head node; + struct acpi_power_resource *resource; }; -static struct list_head acpi_power_resource_list; +static LIST_HEAD(acpi_power_resource_list); +static DEFINE_MUTEX(power_resource_list_lock); /* -------------------------------------------------------------------------- Power Resource Management -------------------------------------------------------------------------- */ -static int -acpi_power_get_context(acpi_handle handle, - struct acpi_power_resource **resource) +static inline +struct acpi_power_resource *to_power_resource(struct acpi_device *device) { - int result = 0; - struct acpi_device *device = NULL; + return container_of(device, struct acpi_power_resource, device); +} +static struct acpi_power_resource *acpi_power_get_context(acpi_handle handle) +{ + struct acpi_device *device; - if (!resource) - return -ENODEV; + if (acpi_bus_get_device(handle, &device)) + return NULL; - result = acpi_bus_get_device(handle, &device); - if (result) { - printk(KERN_WARNING PREFIX "Getting context [%p]\n", handle); - return result; - } + return to_power_resource(device); +} - *resource = acpi_driver_data(device); - if (!*resource) - return -ENODEV; +static int acpi_power_resources_list_add(acpi_handle handle, + struct list_head *list) +{ + struct acpi_power_resource *resource = acpi_power_get_context(handle); + struct acpi_power_resource_entry *entry; + + if (!resource || !list) + return -EINVAL; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + entry->resource = resource; + if (!list_empty(list)) { + struct acpi_power_resource_entry *e; + + list_for_each_entry(e, list, node) + if (e->resource->order > resource->order) { + list_add_tail(&entry->node, &e->node); + return 0; + } + } + list_add_tail(&entry->node, list); return 0; } +void acpi_power_resources_list_free(struct list_head *list) +{ + struct acpi_power_resource_entry *entry, *e; + + list_for_each_entry_safe(entry, e, list, node) { + list_del(&entry->node); + kfree(entry); + } +} + +int acpi_extract_power_resources(union acpi_object *package, unsigned int start, + struct list_head *list) +{ + unsigned int i; + int err = 0; + + for (i = start; i < package->package.count; i++) { + union acpi_object *element = &package->package.elements[i]; + acpi_handle rhandle; + + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { + err = -ENODATA; + break; + } + rhandle = element->reference.handle; + if (!rhandle) { + err = -ENODEV; + break; + } + err = acpi_add_power_resource(rhandle); + if (err) + break; + + err = acpi_power_resources_list_add(rhandle, list); + if (err) + break; + } + if (err) + acpi_power_resources_list_free(list); + + return err; +} + static int acpi_power_get_state(acpi_handle handle, int *state) { acpi_status status = AE_OK; @@ -167,31 +202,23 @@ static int acpi_power_get_state(acpi_handle handle, int *state) return 0; } -static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) +static int acpi_power_get_list_state(struct list_head *list, int *state) { + struct acpi_power_resource_entry *entry; int cur_state; - int i = 0; if (!list || !state) return -EINVAL; /* The state of the list is 'on' IFF all resources are 'on'. */ - - for (i = 0; i < list->count; i++) { - struct acpi_power_resource *resource; - acpi_handle handle = list->handles[i]; + list_for_each_entry(entry, list, node) { + struct acpi_power_resource *resource = entry->resource; + acpi_handle handle = resource->device.handle; int result; - result = acpi_power_get_context(handle, &resource); - if (result) - return result; - mutex_lock(&resource->resource_lock); - result = acpi_power_get_state(handle, &cur_state); - mutex_unlock(&resource->resource_lock); - if (result) return result; @@ -203,56 +230,52 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state) cur_state ? "on" : "off")); *state = cur_state; - return 0; } -/* Resume the device when all power resources in _PR0 are on */ -static void acpi_power_on_device(struct acpi_power_managed_device *device) +static void acpi_power_resume_dependent(struct work_struct *work) { - struct acpi_device *acpi_dev; - acpi_handle handle = device->handle; + struct acpi_power_dependent_device *dep; + struct acpi_device_physical_node *pn; + struct acpi_device *adev; int state; - if (acpi_bus_get_device(handle, &acpi_dev)) + dep = container_of(work, struct acpi_power_dependent_device, work); + adev = dep->adev; + if (acpi_power_get_inferred_state(adev, &state)) return; - if(acpi_power_get_inferred_state(acpi_dev, &state)) + if (state > ACPI_STATE_D0) return; - if (state == ACPI_STATE_D0 && pm_runtime_suspended(device->dev)) - pm_request_resume(device->dev); + mutex_lock(&adev->physical_node_lock); + + list_for_each_entry(pn, &adev->physical_node_list, node) + pm_request_resume(pn->dev); + + list_for_each_entry(pn, &adev->power_dependent, node) + pm_request_resume(pn->dev); + + mutex_unlock(&adev->physical_node_lock); } static int __acpi_power_on(struct acpi_power_resource *resource) { acpi_status status = AE_OK; - status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); + status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL); if (ACPI_FAILURE(status)) return -ENODEV; - /* Update the power resource's _device_ power state */ - resource->device->power.state = ACPI_STATE_D0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); return 0; } -static int acpi_power_on(acpi_handle handle) +static int acpi_power_on_unlocked(struct acpi_power_resource *resource) { 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) - return result; - - mutex_lock(&resource->resource_lock); if (resource->ref_count++) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -260,223 +283,288 @@ static int acpi_power_on(acpi_handle handle) resource->name)); } else { result = __acpi_power_on(resource); - if (result) + if (result) { resource->ref_count--; - else - resume_device = true; - } - - mutex_unlock(&resource->resource_lock); + } else { + struct acpi_power_dependent_device *dep; - 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; + list_for_each_entry(dep, &resource->dependent, node) + schedule_work(&dep->work); + } } + return result; +} - mutex_unlock(&resource->devices_lock); +static int acpi_power_on(struct acpi_power_resource *resource) +{ + int result; + mutex_lock(&resource->resource_lock); + result = acpi_power_on_unlocked(resource); + mutex_unlock(&resource->resource_lock); return result; } -static int acpi_power_off(acpi_handle handle) +static int __acpi_power_off(struct acpi_power_resource *resource) { - int result = 0; - acpi_status status = AE_OK; - struct acpi_power_resource *resource = NULL; + acpi_status status; - result = acpi_power_get_context(handle, &resource); - if (result) - return result; + status = acpi_evaluate_object(resource->device.handle, "_OFF", + NULL, NULL); + if (ACPI_FAILURE(status)) + return -ENODEV; - mutex_lock(&resource->resource_lock); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned off\n", + resource->name)); + return 0; +} + +static int acpi_power_off_unlocked(struct acpi_power_resource *resource) +{ + int result = 0; if (!resource->ref_count) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] already off", resource->name)); - goto unlock; + return 0; } if (--resource->ref_count) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] still in use\n", resource->name)); - goto unlock; - } - - status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL); - if (ACPI_FAILURE(status)) { - result = -ENODEV; } else { - /* Update the power resource's _device_ power state */ - resource->device->power.state = ACPI_STATE_D3; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Power resource [%s] turned off\n", - resource->name)); + result = __acpi_power_off(resource); + if (result) + resource->ref_count++; } - - unlock: - mutex_unlock(&resource->resource_lock); - return result; } -static void __acpi_power_off_list(struct acpi_handle_list *list, int num_res) +static int acpi_power_off(struct acpi_power_resource *resource) { - int i; + int result; - for (i = num_res - 1; i >= 0 ; i--) - acpi_power_off(list->handles[i]); + mutex_lock(&resource->resource_lock); + result = acpi_power_off_unlocked(resource); + mutex_unlock(&resource->resource_lock); + return result; } -static void acpi_power_off_list(struct acpi_handle_list *list) +static int acpi_power_off_list(struct list_head *list) { - __acpi_power_off_list(list, list->count); + struct acpi_power_resource_entry *entry; + int result = 0; + + list_for_each_entry_reverse(entry, list, node) { + result = acpi_power_off(entry->resource); + if (result) + goto err; + } + return 0; + + err: + list_for_each_entry_continue(entry, list, node) + acpi_power_on(entry->resource); + + return result; } -static int acpi_power_on_list(struct acpi_handle_list *list) +static int acpi_power_on_list(struct list_head *list) { + struct acpi_power_resource_entry *entry; int result = 0; - int i; - for (i = 0; i < list->count; i++) { - result = acpi_power_on(list->handles[i]); - if (result) { - __acpi_power_off_list(list, i); - break; - } + list_for_each_entry(entry, list, node) { + result = acpi_power_on(entry->resource); + if (result) + goto err; } + return 0; + + err: + list_for_each_entry_continue_reverse(entry, list, node) + acpi_power_off(entry->resource); return result; } -static void __acpi_power_resource_unregister_device(struct device *dev, - acpi_handle res_handle) +static void acpi_power_add_dependent(struct acpi_power_resource *resource, + struct acpi_device *adev) { - struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *prev, *curr; + struct acpi_power_dependent_device *dep; - if (acpi_power_get_context(res_handle, &resource)) - return; + mutex_lock(&resource->resource_lock); + + list_for_each_entry(dep, &resource->dependent, node) + if (dep->adev == adev) + goto out; + + dep = kzalloc(sizeof(*dep), GFP_KERNEL); + if (!dep) + goto out; - mutex_lock(&resource->devices_lock); - prev = NULL; - curr = resource->devices; - while (curr) { - if (curr->device->dev == dev) { - if (!prev) - resource->devices = curr->next; - else - prev->next = curr->next; - - kfree(curr); + dep->adev = adev; + INIT_WORK(&dep->work, acpi_power_resume_dependent); + list_add_tail(&dep->node, &resource->dependent); + + out: + mutex_unlock(&resource->resource_lock); +} + +static void acpi_power_remove_dependent(struct acpi_power_resource *resource, + struct acpi_device *adev) +{ + struct acpi_power_dependent_device *dep; + struct work_struct *work = NULL; + + mutex_lock(&resource->resource_lock); + + list_for_each_entry(dep, &resource->dependent, node) + if (dep->adev == adev) { + list_del(&dep->node); + work = &dep->work; break; } - prev = curr; - curr = curr->next; + mutex_unlock(&resource->resource_lock); + + if (work) { + cancel_work_sync(work); + kfree(dep); } - mutex_unlock(&resource->devices_lock); } -/* Unlink dev from all power resources in _PR0 */ -void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle) -{ - struct acpi_device *acpi_dev; - struct acpi_handle_list *list; - int i; +static struct attribute *attrs[] = { + NULL, +}; - if (!dev || !handle) - return; +static struct attribute_group attr_groups[] = { + [ACPI_STATE_D0] = { + .name = "power_resources_D0", + .attrs = attrs, + }, + [ACPI_STATE_D1] = { + .name = "power_resources_D1", + .attrs = attrs, + }, + [ACPI_STATE_D2] = { + .name = "power_resources_D2", + .attrs = attrs, + }, + [ACPI_STATE_D3_HOT] = { + .name = "power_resources_D3hot", + .attrs = attrs, + }, +}; + +static void acpi_power_hide_list(struct acpi_device *adev, int state) +{ + struct acpi_device_power_state *ps = &adev->power.states[state]; + struct acpi_power_resource_entry *entry; - if (acpi_bus_get_device(handle, &acpi_dev)) + if (list_empty(&ps->resources)) return; - list = &acpi_dev->power.states[ACPI_STATE_D0].resources; + list_for_each_entry_reverse(entry, &ps->resources, node) { + struct acpi_device *res_dev = &entry->resource->device; - for (i = 0; i < list->count; i++) - __acpi_power_resource_unregister_device(dev, - list->handles[i]); + sysfs_remove_link_from_group(&adev->dev.kobj, + attr_groups[state].name, + dev_name(&res_dev->dev)); + } + sysfs_remove_group(&adev->dev.kobj, &attr_groups[state]); } -EXPORT_SYMBOL_GPL(acpi_power_resource_unregister_device); -static int __acpi_power_resource_register_device( - struct acpi_power_managed_device *powered_device, acpi_handle handle) +static void acpi_power_expose_list(struct acpi_device *adev, int state) { - struct acpi_power_resource *resource = NULL; - struct acpi_power_resource_device *power_resource_device; - int result; - - result = acpi_power_get_context(handle, &resource); - if (result) - return result; + struct acpi_device_power_state *ps = &adev->power.states[state]; + struct acpi_power_resource_entry *entry; + int ret; - power_resource_device = kzalloc( - sizeof(*power_resource_device), GFP_KERNEL); - if (!power_resource_device) - return -ENOMEM; + if (list_empty(&ps->resources)) + return; - power_resource_device->device = powered_device; + ret = sysfs_create_group(&adev->dev.kobj, &attr_groups[state]); + if (ret) + return; - mutex_lock(&resource->devices_lock); - power_resource_device->next = resource->devices; - resource->devices = power_resource_device; - mutex_unlock(&resource->devices_lock); + list_for_each_entry(entry, &ps->resources, node) { + struct acpi_device *res_dev = &entry->resource->device; - return 0; + ret = sysfs_add_link_to_group(&adev->dev.kobj, + attr_groups[state].name, + &res_dev->dev.kobj, + dev_name(&res_dev->dev)); + if (ret) { + acpi_power_hide_list(adev, state); + break; + } + } } -/* Link dev to all power resources in _PR0 */ -int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) +void acpi_power_add_remove_device(struct acpi_device *adev, bool add) { - struct acpi_device *acpi_dev; - struct acpi_handle_list *list; - struct acpi_power_managed_device *powered_device; - int i, ret; + struct acpi_device_power_state *ps; + struct acpi_power_resource_entry *entry; + int state; - if (!dev || !handle) - return -ENODEV; + if (!adev->power.flags.power_resources) + return; - ret = acpi_bus_get_device(handle, &acpi_dev); - if (ret) - goto no_power_resource; + ps = &adev->power.states[ACPI_STATE_D0]; + list_for_each_entry(entry, &ps->resources, node) { + struct acpi_power_resource *resource = entry->resource; - if (!acpi_dev->power.flags.power_resources) - goto no_power_resource; + if (add) + acpi_power_add_dependent(resource, adev); + else + acpi_power_remove_dependent(resource, adev); + } - powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL); - if (!powered_device) - return -ENOMEM; + for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) { + if (add) + acpi_power_expose_list(adev, state); + else + acpi_power_hide_list(adev, state); + } +} - powered_device->dev = dev; - powered_device->handle = handle; +int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) +{ + struct acpi_power_resource_entry *entry; + int system_level = 5; - list = &acpi_dev->power.states[ACPI_STATE_D0].resources; + list_for_each_entry(entry, list, node) { + struct acpi_power_resource *resource = entry->resource; + acpi_handle handle = resource->device.handle; + int result; + int state; - for (i = 0; i < list->count; i++) { - ret = __acpi_power_resource_register_device(powered_device, - list->handles[i]); + mutex_lock(&resource->resource_lock); - if (ret) { - acpi_power_resource_unregister_device(dev, handle); - break; + result = acpi_power_get_state(handle, &state); + if (result) { + mutex_unlock(&resource->resource_lock); + return result; } - } - - return ret; + if (state == ACPI_POWER_RESOURCE_STATE_ON) { + resource->ref_count++; + resource->wakeup_enabled = true; + } + if (system_level > resource->system_level) + system_level = resource->system_level; -no_power_resource: - printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); - return -ENODEV; + mutex_unlock(&resource->resource_lock); + } + *system_level_p = system_level; + return 0; } -EXPORT_SYMBOL_GPL(acpi_power_resource_register_device); + +/* -------------------------------------------------------------------------- + Device Power Management + -------------------------------------------------------------------------- */ /** * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in @@ -549,7 +637,8 @@ int acpi_device_sleep_wake(struct acpi_device *dev, */ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) { - int i, err = 0; + struct acpi_power_resource_entry *entry; + int err = 0; if (!dev || !dev->wakeup.flags.valid) return -EINVAL; @@ -559,24 +648,31 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) if (dev->wakeup.prepare_count++) goto out; - /* Open power resource */ - for (i = 0; i < dev->wakeup.resources.count; i++) { - int ret = acpi_power_on(dev->wakeup.resources.handles[i]); - if (ret) { - printk(KERN_ERR PREFIX "Transition power state\n"); + list_for_each_entry(entry, &dev->wakeup.resources, node) { + struct acpi_power_resource *resource = entry->resource; + + mutex_lock(&resource->resource_lock); + + if (!resource->wakeup_enabled) { + err = acpi_power_on_unlocked(resource); + if (!err) + resource->wakeup_enabled = true; + } + + mutex_unlock(&resource->resource_lock); + + if (err) { + dev_err(&dev->dev, + "Cannot turn wakeup power resources on\n"); dev->wakeup.flags.valid = 0; - err = -ENODEV; - goto err_out; + goto out; } } - /* - * Passing 3 as the third argument below means the device may be placed - * in arbitrary power state afterwards. + * Passing 3 as the third argument below means the device may be + * put into arbitrary power state afterward. */ err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); - - err_out: if (err) dev->wakeup.prepare_count = 0; @@ -593,7 +689,8 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) */ int acpi_disable_wakeup_device_power(struct acpi_device *dev) { - int i, err = 0; + struct acpi_power_resource_entry *entry; + int err = 0; if (!dev || !dev->wakeup.flags.valid) return -EINVAL; @@ -614,14 +711,24 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) if (err) goto out; - /* Close power resource */ - for (i = 0; i < dev->wakeup.resources.count; i++) { - int ret = acpi_power_off(dev->wakeup.resources.handles[i]); - if (ret) { - printk(KERN_ERR PREFIX "Transition power state\n"); + list_for_each_entry(entry, &dev->wakeup.resources, node) { + struct acpi_power_resource *resource = entry->resource; + + mutex_lock(&resource->resource_lock); + + if (resource->wakeup_enabled) { + err = acpi_power_off_unlocked(resource); + if (!err) + resource->wakeup_enabled = false; + } + + mutex_unlock(&resource->resource_lock); + + if (err) { + dev_err(&dev->dev, + "Cannot turn wakeup power resources off\n"); dev->wakeup.flags.valid = 0; - err = -ENODEV; - goto out; + break; } } @@ -630,14 +737,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) return err; } -/* -------------------------------------------------------------------------- - Device Power Management - -------------------------------------------------------------------------- */ - int acpi_power_get_inferred_state(struct acpi_device *device, int *state) { int result = 0; - struct acpi_handle_list *list = NULL; int list_state = 0; int i = 0; @@ -649,8 +751,9 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) * required for a given D-state are 'on'. */ for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { - list = &device->power.states[i].resources; - if (list->count < 1) + struct list_head *list = &device->power.states[i].resources; + + if (list_empty(list)) continue; result = acpi_power_get_list_state(list, &list_state); @@ -669,7 +772,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) int acpi_power_on_resources(struct acpi_device *device, int state) { - if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3) + if (!device || state < ACPI_STATE_D0 || state > ACPI_STATE_D3_HOT) return -EINVAL; return acpi_power_on_list(&device->power.states[state].resources); @@ -682,7 +785,7 @@ int acpi_power_transition(struct acpi_device *device, int state) if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) return -EINVAL; - if (device->power.state == state) + if (device->power.state == state || !device->flags.power_manageable) return 0; if ((device->power.state < ACPI_STATE_D0) @@ -710,118 +813,126 @@ int acpi_power_transition(struct acpi_device *device, int state) return result; } -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ +static void acpi_release_power_resource(struct device *dev) +{ + struct acpi_device *device = to_acpi_device(dev); + struct acpi_power_resource *resource; + + resource = container_of(device, struct acpi_power_resource, device); + + mutex_lock(&power_resource_list_lock); + list_del(&resource->list_node); + mutex_unlock(&power_resource_list_lock); + + acpi_free_ids(device); + kfree(resource); +} + +static ssize_t acpi_power_in_use_show(struct device *dev, + struct device_attribute *attr, + char *buf) { + struct acpi_power_resource *resource; + + resource = to_power_resource(to_acpi_device(dev)); + return sprintf(buf, "%u\n", !!resource->ref_count); +} +static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL); -static int acpi_power_add(struct acpi_device *device) +static void acpi_power_sysfs_remove(struct acpi_device *device) { - int result = 0, state; - acpi_status status = AE_OK; - struct acpi_power_resource *resource = NULL; + device_remove_file(&device->dev, &dev_attr_resource_in_use); +} + +int acpi_add_power_resource(acpi_handle handle) +{ + struct acpi_power_resource *resource; + struct acpi_device *device = NULL; union acpi_object acpi_object; struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object }; + acpi_status status; + int state, result = -ENODEV; + acpi_bus_get_device(handle, &device); + if (device) + return 0; - if (!device) - return -EINVAL; - - resource = kzalloc(sizeof(struct acpi_power_resource), GFP_KERNEL); + resource = kzalloc(sizeof(*resource), GFP_KERNEL); if (!resource) return -ENOMEM; - resource->device = device; + device = &resource->device; + acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER, + ACPI_STA_DEFAULT); mutex_init(&resource->resource_lock); - mutex_init(&resource->devices_lock); - strcpy(resource->name, device->pnp.bus_id); + INIT_LIST_HEAD(&resource->dependent); + resource->name = device->pnp.bus_id; strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); - device->driver_data = resource; + device->power.state = ACPI_STATE_UNKNOWN; /* Evalute the object to get the system level and resource order. */ - status = acpi_evaluate_object(device->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto end; - } + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) + goto err; + resource->system_level = acpi_object.power_resource.system_level; resource->order = acpi_object.power_resource.resource_order; - result = acpi_power_get_state(device->handle, &state); + result = acpi_power_get_state(handle, &state); if (result) - goto end; - - switch (state) { - case ACPI_POWER_RESOURCE_STATE_ON: - device->power.state = ACPI_STATE_D0; - break; - case ACPI_POWER_RESOURCE_STATE_OFF: - device->power.state = ACPI_STATE_D3; - break; - default: - device->power.state = ACPI_STATE_UNKNOWN; - break; - } + goto err; printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), state ? "on" : "off"); - end: + device->flags.match_driver = true; + result = acpi_device_add(device, acpi_release_power_resource); if (result) - kfree(resource); + goto err; - return result; -} - -static int acpi_power_remove(struct acpi_device *device, int type) -{ - struct acpi_power_resource *resource; - - if (!device) - return -EINVAL; - - resource = acpi_driver_data(device); - if (!resource) - return -EINVAL; - - kfree(resource); + if (!device_create_file(&device->dev, &dev_attr_resource_in_use)) + device->remove = acpi_power_sysfs_remove; + mutex_lock(&power_resource_list_lock); + list_add(&resource->list_node, &acpi_power_resource_list); + mutex_unlock(&power_resource_list_lock); + acpi_device_add_finalize(device); return 0; + + err: + acpi_release_power_resource(&device->dev); + return result; } -#ifdef CONFIG_PM_SLEEP -static int acpi_power_resume(struct device *dev) +#ifdef CONFIG_ACPI_SLEEP +void acpi_resume_power_resources(void) { - int result = 0, state; - struct acpi_device *device; struct acpi_power_resource *resource; - if (!dev) - return -EINVAL; + mutex_lock(&power_resource_list_lock); - device = to_acpi_device(dev); - resource = acpi_driver_data(device); - if (!resource) - return -EINVAL; + list_for_each_entry(resource, &acpi_power_resource_list, list_node) { + int result, state; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->resource_lock); - result = acpi_power_get_state(device->handle, &state); - if (result) - goto unlock; + result = acpi_power_get_state(resource->device.handle, &state); + if (result) + continue; - if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count) - result = __acpi_power_on(resource); + if (state == ACPI_POWER_RESOURCE_STATE_OFF + && resource->ref_count) { + dev_info(&resource->device.dev, "Turning ON\n"); + __acpi_power_on(resource); + } else if (state == ACPI_POWER_RESOURCE_STATE_ON + && !resource->ref_count) { + dev_info(&resource->device.dev, "Turning OFF\n"); + __acpi_power_off(resource); + } - unlock: - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->resource_lock); + } - return result; + mutex_unlock(&power_resource_list_lock); } #endif - -int __init acpi_power_init(void) -{ - INIT_LIST_HEAD(&acpi_power_resource_list); - return acpi_bus_register_driver(&acpi_power_driver); -} diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 27adb090bb30..52ce76725c20 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -311,11 +311,12 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->pnp.bus_id, (u32) dev->wakeup.sleep_state); - if (!dev->physical_node_count) + if (!dev->physical_node_count) { seq_printf(seq, "%c%-8s\n", - dev->wakeup.flags.run_wake ? - '*' : ' ', "disabled"); - else { + dev->wakeup.flags.run_wake ? '*' : ' ', + device_may_wakeup(&dev->dev) ? + "enabled" : "disabled"); + } else { struct device *ldev; list_for_each_entry(entry, &dev->physical_node_list, node) { @@ -362,16 +363,13 @@ acpi_system_write_wakeup_device(struct file *file, struct list_head *node, *next; char strbuf[5]; char str[5] = ""; - unsigned int len = count; - if (len > 4) - len = 4; - if (len < 0) - return -EFAULT; + if (count > 4) + count = 4; - if (copy_from_user(strbuf, buffer, len)) + if (copy_from_user(strbuf, buffer, count)) return -EFAULT; - strbuf[len] = '\0'; + strbuf[count] = '\0'; sscanf(strbuf, "%s", str); mutex_lock(&acpi_device_lock); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index eff722278ff5..164d49569aeb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -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; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index bd4e5dca3ff7..bec717ffd25f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -44,6 +44,8 @@ #include <linux/moduleparam.h> #include <linux/cpuidle.h> #include <linux/slab.h> +#include <linux/acpi.h> +#include <linux/memory_hotplug.h> #include <asm/io.h> #include <asm/cpu.h> @@ -80,7 +82,7 @@ MODULE_DESCRIPTION("ACPI Processor Driver"); MODULE_LICENSE("GPL"); static int acpi_processor_add(struct acpi_device *device); -static int acpi_processor_remove(struct acpi_device *device, int type); +static int acpi_processor_remove(struct acpi_device *device); static void acpi_processor_notify(struct acpi_device *device, u32 event); static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr); static int acpi_processor_handle_eject(struct acpi_processor *pr); @@ -282,7 +284,9 @@ static int acpi_processor_get_info(struct acpi_device *device) /* Declared with "Processor" statement; match ProcessorID */ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Evaluating processor object\n"); + dev_err(&device->dev, + "Failed to evaluate processor object (0x%x)\n", + status); return -ENODEV; } @@ -301,8 +305,9 @@ static int acpi_processor_get_info(struct acpi_device *device) status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Evaluating processor _UID [%#x]\n", status); + dev_err(&device->dev, + "Failed to evaluate processor _UID (0x%x)\n", + status); return -ENODEV; } device_declaration = 1; @@ -345,7 +350,7 @@ static int acpi_processor_get_info(struct acpi_device *device) if (!object.processor.pblk_address) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); else if (object.processor.pblk_length != 6) - printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n", + dev_err(&device->dev, "Invalid PBLK length [%d]\n", object.processor.pblk_length); else { pr->throttling.address = object.processor.pblk_address; @@ -430,8 +435,8 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, * Initialize missing things */ if (pr->flags.need_hotplug_init) { - printk(KERN_INFO "Will online and init hotplugged " - "CPU: %d\n", pr->id); + pr_info("Will online and init hotplugged CPU: %d\n", + pr->id); WARN(acpi_processor_start(pr), "Failed to start CPU:" " %d\n", pr->id); pr->flags.need_hotplug_init = 0; @@ -492,14 +497,16 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) &pr->cdev->device.kobj, "thermal_cooling"); if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); + dev_err(&device->dev, + "Failed to create sysfs link 'thermal_cooling'\n"); goto err_thermal_unregister; } result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj, "device"); if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); + dev_err(&pr->cdev->device, + "Failed to create sysfs link 'device'\n"); goto err_remove_sysfs_thermal; } @@ -552,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 @@ -561,8 +568,9 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) */ if (per_cpu(processor_device_array, pr->id) != NULL && per_cpu(processor_device_array, pr->id) != device) { - printk(KERN_WARNING "BIOS reported wrong ACPI id " - "for the processor\n"); + dev_warn(&device->dev, + "BIOS reported wrong ACPI id %d for the processor\n", + pr->id); result = -ENODEV; goto err_free_cpumask; } @@ -603,7 +611,7 @@ err_free_pr: return result; } -static int acpi_processor_remove(struct acpi_device *device, int type) +static int acpi_processor_remove(struct acpi_device *device) { struct acpi_processor *pr = NULL; @@ -616,7 +624,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) if (pr->id >= nr_cpu_ids) goto free; - if (type == ACPI_BUS_REMOVAL_EJECT) { + if (device->removal_type == ACPI_BUS_REMOVAL_EJECT) { if (acpi_processor_handle_eject(pr)) return -EINVAL; } @@ -634,6 +642,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) per_cpu(processors, pr->id) = NULL; per_cpu(processor_device_array, pr->id) = NULL; + try_offline_node(cpu_to_node(pr->id)); free: free_cpumask_var(pr->throttling.shared_cpu_map); @@ -670,36 +679,17 @@ static int is_processor_present(acpi_handle handle) return 0; } -static -int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } - - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { - return -ENODEV; - } - - return 0; -} - static void acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_processor *pr; struct acpi_device *device = NULL; + struct acpi_eject_event *ej_event = NULL; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ + acpi_status status; int result; + acpi_scan_lock_acquire(); + switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: @@ -714,12 +704,16 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_processor_device_add(handle, &device); + result = acpi_bus_scan(handle); if (result) { - printk(KERN_ERR PREFIX "Unable to add the device\n"); + acpi_handle_err(handle, "Unable to add the device\n"); + break; + } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_err(handle, "Missing device object\n"); break; } - ost_code = ACPI_OST_SC_SUCCESS; break; @@ -728,32 +722,48 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, "received ACPI_NOTIFY_EJECT_REQUEST\n")); if (acpi_bus_get_device(handle, &device)) { - printk(KERN_ERR PREFIX - "Device don't exist, dropping EJECT\n"); + acpi_handle_err(handle, + "Device don't exist, dropping EJECT\n"); break; } - pr = acpi_driver_data(device); - if (!pr) { - printk(KERN_ERR PREFIX - "Driver data is NULL, dropping EJECT\n"); + if (!acpi_driver_data(device)) { + acpi_handle_err(handle, + "Driver data is NULL, dropping EJECT\n"); break; } - /* REVISIT: update when eject is supported */ - ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - break; + ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); + if (!ej_event) { + acpi_handle_err(handle, "No memory, dropping EJECT\n"); + break; + } + + get_device(&device->dev); + ej_event->device = device; + ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; + /* The eject is carried out asynchronously. */ + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, + ej_event); + if (ACPI_FAILURE(status)) { + put_device(&device->dev); + kfree(ej_event); + break; + } + goto out; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); /* non-hotplug event; possibly handled by other handler */ - return; + goto out; } /* Inform firmware that the hotplug operation has completed */ (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - return; + + out: + acpi_scan_lock_release(); } static acpi_status is_processor_device(acpi_handle handle) @@ -841,7 +851,7 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr) * and do it when the CPU gets online the first time * TBD: Cleanup above functions and try to do this more elegant. */ - printk(KERN_INFO "CPU %d got hotplugged\n", pr->id); + pr_info("CPU %d got hotplugged\n", pr->id); pr->flags.need_hotplug_init = 1; return AE_OK; @@ -852,8 +862,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr) if (cpu_online(pr->id)) cpu_down(pr->id); + get_online_cpus(); + /* + * The cpu might become online again at this point. So we check whether + * the cpu has been onlined or not. If the cpu became online, it means + * that someone wants to use the cpu. So acpi_processor_handle_eject() + * returns -EAGAIN. + */ + if (unlikely(cpu_online(pr->id))) { + put_online_cpus(); + pr_warn("Failed to remove CPU %d, because other task " + "brought the CPU back online\n", pr->id); + return -EAGAIN; + } arch_unregister_cpu(pr->id); acpi_unmap_lsapic(pr->id); + put_online_cpus(); return (0); } #else diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e8086c725305..fc95308e9a11 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -28,19 +28,12 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> -#include <linux/cpufreq.h> -#include <linux/slab.h> #include <linux/acpi.h> #include <linux/dmi.h> -#include <linux/moduleparam.h> -#include <linux/sched.h> /* need_resched() */ -#include <linux/pm_qos.h> +#include <linux/sched.h> /* need_resched() */ #include <linux/clockchips.h> #include <linux/cpuidle.h> -#include <linux/irqflags.h> /* * Include the apic definitions for x86 to have the APIC timer related defines @@ -52,22 +45,14 @@ #include <asm/apic.h> #endif -#include <asm/io.h> -#include <asm/uaccess.h> - #include <acpi/acpi_bus.h> #include <acpi/processor.h> -#include <asm/processor.h> #define PREFIX "ACPI: " #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_idle"); -#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) -#define C2_OVERHEAD 1 /* 1us */ -#define C3_OVERHEAD 1 /* 1us */ -#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; module_param(max_cstate, uint, 0000); @@ -81,10 +66,11 @@ module_param(latency_factor, uint, 0644); static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); +static struct acpi_processor_cx *acpi_cstate[CPUIDLE_STATE_MAX]; + static int disabled_by_idle_boot_param(void) { return boot_option_idle_override == IDLE_POLL || - boot_option_idle_override == IDLE_FORCE_MWAIT || boot_option_idle_override == IDLE_HALT; } @@ -735,31 +721,17 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - ktime_t kt1, kt2; - s64 idle_time; struct acpi_processor *pr; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); + struct acpi_processor_cx *cx = acpi_cstate[index]; pr = __this_cpu_read(processors); - dev->last_residency = 0; if (unlikely(!pr)) return -EINVAL; - local_irq_disable(); - - lapic_timer_state_broadcast(pr, cx, 1); - kt1 = ktime_get_real(); acpi_idle_do_entry(cx); - kt2 = ktime_get_real(); - idle_time = ktime_to_us(ktime_sub(kt2, kt1)); - /* Update device last_residency*/ - dev->last_residency = (int)idle_time; - - local_irq_enable(); lapic_timer_state_broadcast(pr, cx, 0); return index; @@ -773,8 +745,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, */ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) { - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); + struct acpi_processor_cx *cx = acpi_cstate[index]; ACPI_FLUSH_CPU_CACHE(); @@ -804,21 +775,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct acpi_processor *pr; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); - ktime_t kt1, kt2; - s64 idle_time_ns; - s64 idle_time; + struct acpi_processor_cx *cx = acpi_cstate[index]; pr = __this_cpu_read(processors); - dev->last_residency = 0; if (unlikely(!pr)) return -EINVAL; - local_irq_disable(); - - if (cx->entry_method != ACPI_CSTATE_FFH) { current_thread_info()->status &= ~TS_POLLING; /* @@ -829,7 +792,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; - local_irq_enable(); return -EINVAL; } } @@ -843,22 +805,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (cx->type == ACPI_STATE_C3) ACPI_FLUSH_CPU_CACHE(); - kt1 = ktime_get_real(); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); acpi_idle_do_entry(cx); - kt2 = ktime_get_real(); - idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1)); - idle_time = idle_time_ns; - do_div(idle_time, NSEC_PER_USEC); - - /* Update device last_residency*/ - dev->last_residency = (int)idle_time; - /* Tell the scheduler how much we idled: */ - sched_clock_idle_wakeup_event(idle_time_ns); + sched_clock_idle_wakeup_event(0); - local_irq_enable(); if (cx->entry_method != ACPI_CSTATE_FFH) current_thread_info()->status |= TS_POLLING; @@ -881,15 +833,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct acpi_processor *pr; - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); - ktime_t kt1, kt2; - s64 idle_time_ns; - s64 idle_time; - + struct acpi_processor_cx *cx = acpi_cstate[index]; pr = __this_cpu_read(processors); - dev->last_residency = 0; if (unlikely(!pr)) return -EINVAL; @@ -899,16 +845,11 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return drv->states[drv->safe_state_index].enter(dev, drv, drv->safe_state_index); } else { - local_irq_disable(); acpi_safe_halt(); - local_irq_enable(); return -EBUSY; } } - local_irq_disable(); - - if (cx->entry_method != ACPI_CSTATE_FFH) { current_thread_info()->status &= ~TS_POLLING; /* @@ -919,7 +860,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; - local_irq_enable(); return -EINVAL; } } @@ -934,7 +874,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, */ lapic_timer_state_broadcast(pr, cx, 1); - kt1 = ktime_get_real(); /* * disable bus master * bm_check implies we need ARB_DIS @@ -965,18 +904,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, c3_cpu_count--; raw_spin_unlock(&c3_lock); } - kt2 = ktime_get_real(); - idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1)); - idle_time = idle_time_ns; - do_div(idle_time, NSEC_PER_USEC); - - /* Update device last_residency*/ - dev->last_residency = (int)idle_time; - /* Tell the scheduler how much we idled: */ - sched_clock_idle_wakeup_event(idle_time_ns); + sched_clock_idle_wakeup_event(0); - local_irq_enable(); if (cx->entry_method != ACPI_CSTATE_FFH) current_thread_info()->status |= TS_POLLING; @@ -987,6 +917,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct cpuidle_driver acpi_idle_driver = { .name = "acpi_idle", .owner = THIS_MODULE, + .en_core_tk_irqen = 1, }; /** @@ -994,13 +925,13 @@ struct cpuidle_driver acpi_idle_driver = { * device i.e. per-cpu data * * @pr: the ACPI processor + * @dev : the cpuidle device */ -static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) +static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, + struct cpuidle_device *dev) { int i, count = CPUIDLE_DRIVER_STATE_START; struct acpi_processor_cx *cx; - struct cpuidle_state_usage *state_usage; - struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); if (!pr->flags.power_setup_done) return -EINVAL; @@ -1009,6 +940,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) return -EINVAL; } + if (!dev) + return -EINVAL; + dev->cpu = pr->id; if (max_cstate == 0) @@ -1016,7 +950,6 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = &pr->power.states[i]; - state_usage = &dev->states_usage[count]; if (!cx->valid) continue; @@ -1027,8 +960,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) continue; #endif - - cpuidle_set_statedata(state_usage, cx); + acpi_cstate[count] = cx; count++; if (count == CPUIDLE_STATE_MAX) @@ -1152,7 +1084,7 @@ int acpi_processor_hotplug(struct acpi_processor *pr) cpuidle_disable_device(dev); acpi_processor_get_power_info(pr); if (pr->flags.power) { - acpi_processor_setup_cpuidle_cx(pr); + acpi_processor_setup_cpuidle_cx(pr, dev); ret = cpuidle_enable_device(dev); } cpuidle_resume_and_unlock(); @@ -1200,6 +1132,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) } /* Populate Updated C-state information */ + acpi_processor_get_power_info(pr); acpi_processor_setup_cpuidle_states(pr); /* Enable all cpuidle devices */ @@ -1209,8 +1142,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) continue; acpi_processor_get_power_info(_pr); if (_pr->flags.power) { - acpi_processor_setup_cpuidle_cx(_pr); dev = per_cpu(acpi_cpuidle_device, cpu); + acpi_processor_setup_cpuidle_cx(_pr, dev); cpuidle_enable_device(dev); } } @@ -1279,7 +1212,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr) return -ENOMEM; per_cpu(acpi_cpuidle_device, pr->id) = dev; - acpi_processor_setup_cpuidle_cx(pr); + acpi_processor_setup_cpuidle_cx(pr, dev); /* Register per-cpu cpuidle_device. Cpuidle driver * must already be registered before registering device diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 836bfe069042..e854582f29a6 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) || boot_cpu_data.x86 == 0x11) { rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); + /* + * MSR C001_0064+: + * Bit 63: PstateEn. Read-write. If set, the P-state is valid. + */ + if (!(hi & BIT(31))) + return; + fid = lo & 0x3f; did = (lo >> 6) & 7; if (boot_cpu_data.x86 == 0x10) @@ -458,7 +465,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) return result; } -static int acpi_processor_get_performance_info(struct acpi_processor *pr) +int acpi_processor_get_performance_info(struct acpi_processor *pr) { int result = 0; acpi_status status = AE_OK; @@ -502,7 +509,7 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) #endif return result; } - +EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info); int acpi_processor_notify_smm(struct module *calling_module) { acpi_status status; diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c new file mode 100644 index 000000000000..a3868f6c222a --- /dev/null +++ b/drivers/acpi/resource.c @@ -0,0 +1,526 @@ +/* + * drivers/acpi/resource.c - ACPI device resources interpretation. + * + * Copyright (C) 2012, Intel Corp. + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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 published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include <linux/acpi.h> +#include <linux/device.h> +#include <linux/export.h> +#include <linux/ioport.h> +#include <linux/slab.h> + +#ifdef CONFIG_X86 +#define valid_IRQ(i) (((i) != 0) && ((i) != 2)) +#else +#define valid_IRQ(i) (true) +#endif + +static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect, + bool window) +{ + unsigned long flags = IORESOURCE_MEM; + + if (len == 0) + flags |= IORESOURCE_DISABLED; + + if (write_protect == ACPI_READ_WRITE_MEMORY) + flags |= IORESOURCE_MEM_WRITEABLE; + + if (window) + flags |= IORESOURCE_WINDOW; + + return flags; +} + +static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, + u8 write_protect) +{ + res->start = start; + res->end = start + len - 1; + res->flags = acpi_dev_memresource_flags(len, write_protect, false); +} + +/** + * acpi_dev_resource_memory - Extract ACPI memory resource information. + * @ares: Input ACPI resource object. + * @res: Output generic resource object. + * + * Check if the given ACPI resource object represents a memory resource and + * if that's the case, use the information in it to populate the generic + * resource object pointed to by @res. + */ +bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) +{ + struct acpi_resource_memory24 *memory24; + struct acpi_resource_memory32 *memory32; + struct acpi_resource_fixed_memory32 *fixed_memory32; + + switch (ares->type) { + case ACPI_RESOURCE_TYPE_MEMORY24: + memory24 = &ares->data.memory24; + acpi_dev_get_memresource(res, memory24->minimum, + memory24->address_length, + memory24->write_protect); + break; + case ACPI_RESOURCE_TYPE_MEMORY32: + memory32 = &ares->data.memory32; + acpi_dev_get_memresource(res, memory32->minimum, + memory32->address_length, + memory32->write_protect); + break; + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + fixed_memory32 = &ares->data.fixed_memory32; + acpi_dev_get_memresource(res, fixed_memory32->address, + fixed_memory32->address_length, + fixed_memory32->write_protect); + break; + default: + return false; + } + return true; +} +EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); + +static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode, + bool window) +{ + int flags = IORESOURCE_IO; + + if (io_decode == ACPI_DECODE_16) + flags |= IORESOURCE_IO_16BIT_ADDR; + + if (start > end || end >= 0x10003) + flags |= IORESOURCE_DISABLED; + + if (window) + flags |= IORESOURCE_WINDOW; + + return flags; +} + +static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, + u8 io_decode) +{ + u64 end = start + len - 1; + + res->start = start; + res->end = end; + res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false); +} + +/** + * acpi_dev_resource_io - Extract ACPI I/O resource information. + * @ares: Input ACPI resource object. + * @res: Output generic resource object. + * + * Check if the given ACPI resource object represents an I/O resource and + * if that's the case, use the information in it to populate the generic + * resource object pointed to by @res. + */ +bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) +{ + struct acpi_resource_io *io; + struct acpi_resource_fixed_io *fixed_io; + + switch (ares->type) { + case ACPI_RESOURCE_TYPE_IO: + io = &ares->data.io; + acpi_dev_get_ioresource(res, io->minimum, + io->address_length, + io->io_decode); + break; + case ACPI_RESOURCE_TYPE_FIXED_IO: + fixed_io = &ares->data.fixed_io; + acpi_dev_get_ioresource(res, fixed_io->address, + fixed_io->address_length, + ACPI_DECODE_10); + break; + default: + return false; + } + return true; +} +EXPORT_SYMBOL_GPL(acpi_dev_resource_io); + +/** + * acpi_dev_resource_address_space - Extract ACPI address space information. + * @ares: Input ACPI resource object. + * @res: Output generic resource object. + * + * Check if the given ACPI resource object represents an address space resource + * and if that's the case, use the information in it to populate the generic + * resource object pointed to by @res. + */ +bool acpi_dev_resource_address_space(struct acpi_resource *ares, + struct resource *res) +{ + acpi_status status; + struct acpi_resource_address64 addr; + bool window; + u64 len; + u8 io_decode; + + switch (ares->type) { + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + break; + default: + return false; + } + + status = acpi_resource_to_address64(ares, &addr); + if (ACPI_FAILURE(status)) + return true; + + res->start = addr.minimum; + res->end = addr.maximum; + window = addr.producer_consumer == ACPI_PRODUCER; + + switch(addr.resource_type) { + case ACPI_MEMORY_RANGE: + len = addr.maximum - addr.minimum + 1; + res->flags = acpi_dev_memresource_flags(len, + addr.info.mem.write_protect, + window); + break; + case ACPI_IO_RANGE: + io_decode = addr.granularity == 0xfff ? + ACPI_DECODE_10 : ACPI_DECODE_16; + res->flags = acpi_dev_ioresource_flags(addr.minimum, + addr.maximum, + io_decode, window); + break; + case ACPI_BUS_NUMBER_RANGE: + res->flags = IORESOURCE_BUS; + break; + default: + res->flags = 0; + } + + return true; +} +EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); + +/** + * acpi_dev_resource_ext_address_space - Extract ACPI address space information. + * @ares: Input ACPI resource object. + * @res: Output generic resource object. + * + * Check if the given ACPI resource object represents an extended address space + * resource and if that's the case, use the information in it to populate the + * generic resource object pointed to by @res. + */ +bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, + struct resource *res) +{ + struct acpi_resource_extended_address64 *ext_addr; + bool window; + u64 len; + u8 io_decode; + + if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) + return false; + + ext_addr = &ares->data.ext_address64; + + res->start = ext_addr->minimum; + res->end = ext_addr->maximum; + window = ext_addr->producer_consumer == ACPI_PRODUCER; + + switch(ext_addr->resource_type) { + case ACPI_MEMORY_RANGE: + len = ext_addr->maximum - ext_addr->minimum + 1; + res->flags = acpi_dev_memresource_flags(len, + ext_addr->info.mem.write_protect, + window); + break; + case ACPI_IO_RANGE: + io_decode = ext_addr->granularity == 0xfff ? + ACPI_DECODE_10 : ACPI_DECODE_16; + res->flags = acpi_dev_ioresource_flags(ext_addr->minimum, + ext_addr->maximum, + io_decode, window); + break; + case ACPI_BUS_NUMBER_RANGE: + res->flags = IORESOURCE_BUS; + break; + default: + res->flags = 0; + } + + return true; +} +EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); + +/** + * acpi_dev_irq_flags - Determine IRQ resource flags. + * @triggering: Triggering type as provided by ACPI. + * @polarity: Interrupt polarity as provided by ACPI. + * @shareable: Whether or not the interrupt is shareable. + */ +unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable) +{ + unsigned long flags; + + if (triggering == ACPI_LEVEL_SENSITIVE) + flags = polarity == ACPI_ACTIVE_LOW ? + IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL; + else + flags = polarity == ACPI_ACTIVE_LOW ? + IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE; + + if (shareable == ACPI_SHARED) + flags |= IORESOURCE_IRQ_SHAREABLE; + + return flags | IORESOURCE_IRQ; +} +EXPORT_SYMBOL_GPL(acpi_dev_irq_flags); + +static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) +{ + res->start = gsi; + res->end = gsi; + res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED; +} + +static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, + u8 triggering, u8 polarity, u8 shareable) +{ + int irq, p, t; + + if (!valid_IRQ(gsi)) { + acpi_dev_irqresource_disabled(res, gsi); + return; + } + + /* + * In IO-APIC mode, use overrided attribute. Two reasons: + * 1. BIOS bug in DSDT + * 2. BIOS uses IO-APIC mode Interrupt Source Override + */ + if (!acpi_get_override_irq(gsi, &t, &p)) { + u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; + u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; + + if (triggering != trig || polarity != pol) { + pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, + t ? "edge" : "level", p ? "low" : "high"); + triggering = trig; + polarity = pol; + } + } + + res->flags = acpi_dev_irq_flags(triggering, polarity, shareable); + irq = acpi_register_gsi(NULL, gsi, triggering, polarity); + if (irq >= 0) { + res->start = irq; + res->end = irq; + } else { + acpi_dev_irqresource_disabled(res, gsi); + } +} + +/** + * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information. + * @ares: Input ACPI resource object. + * @index: Index into the array of GSIs represented by the resource. + * @res: Output generic resource object. + * + * Check if the given ACPI resource object represents an interrupt resource + * and @index does not exceed the resource's interrupt count (true is returned + * in that case regardless of the results of the other checks)). If that's the + * case, register the GSI corresponding to @index from the array of interrupts + * represented by the resource and populate the generic resource object pointed + * to by @res accordingly. If the registration of the GSI is not successful, + * IORESOURCE_DISABLED will be set it that object's flags. + */ +bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, + struct resource *res) +{ + struct acpi_resource_irq *irq; + struct acpi_resource_extended_irq *ext_irq; + + switch (ares->type) { + case ACPI_RESOURCE_TYPE_IRQ: + /* + * Per spec, only one interrupt per descriptor is allowed in + * _CRS, but some firmware violates this, so parse them all. + */ + irq = &ares->data.irq; + if (index >= irq->interrupt_count) { + acpi_dev_irqresource_disabled(res, 0); + return false; + } + acpi_dev_get_irqresource(res, irq->interrupts[index], + irq->triggering, irq->polarity, + irq->sharable); + break; + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + ext_irq = &ares->data.extended_irq; + if (index >= ext_irq->interrupt_count) { + acpi_dev_irqresource_disabled(res, 0); + return false; + } + acpi_dev_get_irqresource(res, ext_irq->interrupts[index], + ext_irq->triggering, ext_irq->polarity, + ext_irq->sharable); + break; + default: + return false; + } + + return true; +} +EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt); + +/** + * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources(). + * @list: The head of the resource list to free. + */ +void acpi_dev_free_resource_list(struct list_head *list) +{ + struct resource_list_entry *rentry, *re; + + list_for_each_entry_safe(rentry, re, list, node) { + list_del(&rentry->node); + kfree(rentry); + } +} +EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list); + +struct res_proc_context { + struct list_head *list; + int (*preproc)(struct acpi_resource *, void *); + void *preproc_data; + int count; + int error; +}; + +static acpi_status acpi_dev_new_resource_entry(struct resource *r, + struct res_proc_context *c) +{ + struct resource_list_entry *rentry; + + rentry = kmalloc(sizeof(*rentry), GFP_KERNEL); + if (!rentry) { + c->error = -ENOMEM; + return AE_NO_MEMORY; + } + rentry->res = *r; + list_add_tail(&rentry->node, c->list); + c->count++; + return AE_OK; +} + +static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, + void *context) +{ + struct res_proc_context *c = context; + struct resource r; + int i; + + if (c->preproc) { + int ret; + + ret = c->preproc(ares, c->preproc_data); + if (ret < 0) { + c->error = ret; + return AE_CTRL_TERMINATE; + } else if (ret > 0) { + return AE_OK; + } + } + + memset(&r, 0, sizeof(r)); + + if (acpi_dev_resource_memory(ares, &r) + || acpi_dev_resource_io(ares, &r) + || acpi_dev_resource_address_space(ares, &r) + || acpi_dev_resource_ext_address_space(ares, &r)) + return acpi_dev_new_resource_entry(&r, c); + + for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) { + acpi_status status; + + status = acpi_dev_new_resource_entry(&r, c); + if (ACPI_FAILURE(status)) + return status; + } + + return AE_OK; +} + +/** + * acpi_dev_get_resources - Get current resources of a device. + * @adev: ACPI device node to get the resources for. + * @list: Head of the resultant list of resources (must be empty). + * @preproc: The caller's preprocessing routine. + * @preproc_data: Pointer passed to the caller's preprocessing routine. + * + * Evaluate the _CRS method for the given device node and process its output by + * (1) executing the @preproc() rountine provided by the caller, passing the + * resource pointer and @preproc_data to it as arguments, for each ACPI resource + * returned and (2) converting all of the returned ACPI resources into struct + * resource objects if possible. If the return value of @preproc() in step (1) + * is different from 0, step (2) is not applied to the given ACPI resource and + * if that value is negative, the whole processing is aborted and that value is + * returned as the final error code. + * + * The resultant struct resource objects are put on the list pointed to by + * @list, that must be empty initially, as members of struct resource_list_entry + * objects. Callers of this routine should use %acpi_dev_free_resource_list() to + * free that list. + * + * The number of resources in the output list is returned on success, an error + * code reflecting the error condition is returned otherwise. + */ +int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, + int (*preproc)(struct acpi_resource *, void *), + void *preproc_data) +{ + struct res_proc_context c; + acpi_handle not_used; + acpi_status status; + + if (!adev || !adev->handle || !list_empty(list)) + return -EINVAL; + + status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, ¬_used); + if (ACPI_FAILURE(status)) + return 0; + + c.list = list; + c.preproc = preproc; + c.preproc_data = preproc_data; + c.count = 0; + c.error = 0; + status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS, + acpi_dev_process_resource, &c); + if (ACPI_FAILURE(status)) { + acpi_dev_free_resource_list(list); + return c.error ? c.error : -EIO; + } + + return c.count; +} +EXPORT_SYMBOL_GPL(acpi_dev_get_resources); diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index ff0740e0a9c2..e523245643ac 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -130,7 +130,7 @@ struct acpi_sbs { #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) -static int acpi_sbs_remove(struct acpi_device *device, int type); +static int acpi_sbs_remove(struct acpi_device *device); static int acpi_battery_get_state(struct acpi_battery *battery); static inline int battery_scale(int log) @@ -949,11 +949,11 @@ static int acpi_sbs_add(struct acpi_device *device) acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); end: if (result) - acpi_sbs_remove(device, 0); + acpi_sbs_remove(device); return result; } -static int acpi_sbs_remove(struct acpi_device *device, int type) +static int acpi_sbs_remove(struct acpi_device *device) { struct acpi_sbs *sbs; int id; diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index cf6129a8af7c..b78bc605837e 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -33,7 +33,7 @@ struct acpi_smb_hc { }; static int acpi_smbus_hc_add(struct acpi_device *device); -static int acpi_smbus_hc_remove(struct acpi_device *device, int type); +static int acpi_smbus_hc_remove(struct acpi_device *device); static const struct acpi_device_id sbs_device_ids[] = { {"ACPI0001", 0}, @@ -296,7 +296,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device) extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); -static int acpi_smbus_hc_remove(struct acpi_device *device, int type) +static int acpi_smbus_hc_remove(struct acpi_device *device) { struct acpi_smb_hc *hc; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 1fcb8678665c..5e7e991717d7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -31,6 +31,8 @@ static const char *dummy_hid = "device"; static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_bus_id_list); +static DEFINE_MUTEX(acpi_scan_lock); +static LIST_HEAD(acpi_scan_handlers_list); DEFINE_MUTEX(acpi_device_lock); LIST_HEAD(acpi_wakeup_device_list); @@ -40,6 +42,27 @@ struct acpi_device_bus_id{ struct list_head node; }; +void acpi_scan_lock_acquire(void) +{ + mutex_lock(&acpi_scan_lock); +} +EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire); + +void acpi_scan_lock_release(void) +{ + mutex_unlock(&acpi_scan_lock); +} +EXPORT_SYMBOL_GPL(acpi_scan_lock_release); + +int acpi_scan_add_handler(struct acpi_scan_handler *handler) +{ + if (!handler || !handler->attach) + return -EINVAL; + + list_add_tail(&handler->list_node, &acpi_scan_handlers_list); + return 0; +} + /* * Creates hid/cid(s) string needed for modalias and uevent * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: @@ -94,36 +117,33 @@ static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); */ void acpi_bus_hot_remove_device(void *context) { - struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context; - struct acpi_device *device; - acpi_handle handle = ej_event->handle; + struct acpi_eject_event *ej_event = context; + struct acpi_device *device = ej_event->device; + acpi_handle handle = device->handle; + acpi_handle temp; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ - if (acpi_bus_get_device(handle, &device)) - goto err_out; + mutex_lock(&acpi_scan_lock); - if (!device) - goto err_out; + /* If there is no handle, the device node has been unregistered. */ + if (!device->handle) { + dev_dbg(&device->dev, "ACPI handle missing\n"); + put_device(&device->dev); + goto out; + } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); - if (acpi_bus_trim(device, 1)) { - printk(KERN_ERR PREFIX - "Removing device failed\n"); - goto err_out; - } - - /* power off device */ - status = acpi_evaluate_object(handle, "_PS3", NULL, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) - printk(KERN_WARNING PREFIX - "Power-off device failed\n"); + acpi_bus_trim(device); + /* Device node has been unregistered. */ + put_device(&device->dev); + device = NULL; - if (device->flags.lockable) { + if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { arg_list.count = 1; arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; @@ -142,22 +162,46 @@ void acpi_bus_hot_remove_device(void *context) status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) - printk(KERN_WARNING PREFIX - "Eject device failed\n"); - goto err_out; + acpi_handle_warn(handle, "Eject failed\n"); + + /* Tell the firmware the hot-remove operation has failed. */ + acpi_evaluate_hotplug_ost(handle, ej_event->event, + ost_code, NULL); } + out: + mutex_unlock(&acpi_scan_lock); kfree(context); return; +} +EXPORT_SYMBOL(acpi_bus_hot_remove_device); -err_out: - /* Inform firmware the hot-remove operation has completed w/ error */ - (void) acpi_evaluate_hotplug_ost(handle, - ej_event->event, ost_code, NULL); - kfree(context); - return; +static ssize_t real_power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *adev = to_acpi_device(dev); + int state; + int ret; + + ret = acpi_device_get_power(adev, &state); + if (ret) + return ret; + + return sprintf(buf, "%s\n", acpi_power_state_string(state)); } +static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL); + +static ssize_t power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *adev = to_acpi_device(dev); + + return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state)); +} + +static DEVICE_ATTR(power_state, 0444, power_state_show, NULL); + static ssize_t acpi_eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -171,12 +215,10 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, if ((!count) || (buf[0] != '1')) { return -EINVAL; } -#ifndef FORCE_EJECT - if (acpi_device->driver == NULL) { + if (!acpi_device->driver && !acpi_device->handler) { ret = -ENODEV; goto err; } -#endif status = acpi_get_type(acpi_device->handle, &type); if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { ret = -ENODEV; @@ -189,7 +231,8 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, goto err; } - ej_event->handle = acpi_device->handle; + get_device(&acpi_device->dev); + ej_event->device = acpi_device; if (acpi_device->flags.eject_pending) { /* event originated from ACPI eject notification */ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; @@ -197,11 +240,15 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, } else { /* event originated from user */ ej_event->event = ACPI_OST_EC_OSPM_EJECT; - (void) acpi_evaluate_hotplug_ost(ej_event->handle, + (void) acpi_evaluate_hotplug_ost(acpi_device->handle, ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); } - acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event); + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); + if (ACPI_FAILURE(status)) { + put_device(&acpi_device->dev); + kfree(ej_event); + } err: return ret; } @@ -216,6 +263,25 @@ acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *bu } static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL); +static ssize_t acpi_device_uid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *acpi_dev = to_acpi_device(dev); + + return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id); +} +static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL); + +static ssize_t acpi_device_adr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *acpi_dev = to_acpi_device(dev); + + return sprintf(buf, "0x%08x\n", + (unsigned int)(acpi_dev->pnp.bus_address)); +} +static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL); + static ssize_t acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -259,11 +325,21 @@ static ssize_t description_show(struct device *dev, } static DEVICE_ATTR(description, 0444, description_show, NULL); +static ssize_t +acpi_device_sun_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); + + return sprintf(buf, "%lu\n", acpi_dev->pnp.sun); +} +static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); + static int acpi_device_setup_files(struct acpi_device *dev) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_status status; acpi_handle temp; + unsigned long long sun; int result = 0; /* @@ -300,13 +376,42 @@ static int acpi_device_setup_files(struct acpi_device *dev) goto end; } + if (dev->flags.bus_address) + result = device_create_file(&dev->dev, &dev_attr_adr); + if (dev->pnp.unique_id) + result = device_create_file(&dev->dev, &dev_attr_uid); + + status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun); + if (ACPI_SUCCESS(status)) { + dev->pnp.sun = (unsigned long)sun; + result = device_create_file(&dev->dev, &dev_attr_sun); + if (result) + goto end; + } else { + dev->pnp.sun = (unsigned long)-1; + } + /* * If device has _EJ0, 'eject' file is created that is used to trigger * hot-removal function from userland. */ status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(status)) { result = device_create_file(&dev->dev, &dev_attr_eject); + if (result) + return result; + } + + if (dev->flags.power_manageable) { + result = device_create_file(&dev->dev, &dev_attr_power_state); + if (result) + return result; + + if (dev->power.flags.power_resources) + result = device_create_file(&dev->dev, + &dev_attr_real_power_state); + } + end: return result; } @@ -316,6 +421,13 @@ static void acpi_device_remove_files(struct acpi_device *dev) acpi_status status; acpi_handle temp; + if (dev->flags.power_manageable) { + device_remove_file(&dev->dev, &dev_attr_power_state); + if (dev->power.flags.power_resources) + device_remove_file(&dev->dev, + &dev_attr_real_power_state); + } + /* * If device has _STR, remove 'description' file */ @@ -331,6 +443,14 @@ static void acpi_device_remove_files(struct acpi_device *dev) if (ACPI_SUCCESS(status)) device_remove_file(&dev->dev, &dev_attr_eject); + status = acpi_get_handle(dev->handle, "_SUN", &temp); + if (ACPI_SUCCESS(status)) + device_remove_file(&dev->dev, &dev_attr_sun); + + if (dev->pnp.unique_id) + device_remove_file(&dev->dev, &dev_attr_uid); + if (dev->flags.bus_address) + device_remove_file(&dev->dev, &dev_attr_adr); device_remove_file(&dev->dev, &dev_attr_modalias); device_remove_file(&dev->dev, &dev_attr_hid); if (dev->handle) @@ -340,8 +460,8 @@ static void acpi_device_remove_files(struct acpi_device *dev) ACPI Bus operations -------------------------------------------------------------------------- */ -int acpi_match_device_ids(struct acpi_device *device, - const struct acpi_device_id *ids) +static const struct acpi_device_id *__acpi_match_device( + struct acpi_device *device, const struct acpi_device_id *ids) { const struct acpi_device_id *id; struct acpi_hardware_id *hwid; @@ -351,18 +471,48 @@ int acpi_match_device_ids(struct acpi_device *device, * driver for it. */ if (!device->status.present) - return -ENODEV; + return NULL; for (id = ids; id->id[0]; id++) list_for_each_entry(hwid, &device->pnp.ids, list) if (!strcmp((char *) id->id, hwid->id)) - return 0; + return id; - return -ENOENT; + return NULL; +} + +/** + * acpi_match_device - Match a struct device against a given list of ACPI IDs + * @ids: Array of struct acpi_device_id object to match against. + * @dev: The device structure to match. + * + * Check if @dev has a valid ACPI handle and if there is a struct acpi_device + * object for that handle and use that object to match against a given list of + * device IDs. + * + * Return a pointer to the first matching ID on success or %NULL on failure. + */ +const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, + const struct device *dev) +{ + struct acpi_device *adev; + acpi_handle handle = ACPI_HANDLE(dev); + + if (!ids || !handle || acpi_bus_get_device(handle, &adev)) + return NULL; + + return __acpi_match_device(adev, ids); +} +EXPORT_SYMBOL_GPL(acpi_match_device); + +int acpi_match_device_ids(struct acpi_device *device, + const struct acpi_device_id *ids) +{ + return __acpi_match_device(device, ids) ? 0 : -ENOENT; } EXPORT_SYMBOL(acpi_match_device_ids); -static void acpi_free_ids(struct acpi_device *device) +void acpi_free_ids(struct acpi_device *device) { struct acpi_hardware_id *id, *tmp; @@ -370,6 +520,23 @@ static void acpi_free_ids(struct acpi_device *device) kfree(id->id); kfree(id); } + kfree(device->pnp.unique_id); +} + +static void acpi_free_power_resources_lists(struct acpi_device *device) +{ + int i; + + if (device->wakeup.flags.valid) + acpi_power_resources_list_free(&device->wakeup.resources); + + if (!device->flags.power_manageable) + return; + + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { + struct acpi_device_power_state *ps = &device->power.states[i]; + acpi_power_resources_list_free(&ps->resources); + } } static void acpi_device_release(struct device *dev) @@ -377,6 +544,7 @@ static void acpi_device_release(struct device *dev) struct acpi_device *acpi_dev = to_acpi_device(dev); acpi_free_ids(acpi_dev); + acpi_free_power_resources_lists(acpi_dev); kfree(acpi_dev); } @@ -385,7 +553,8 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->flags.match_driver + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -461,7 +630,6 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) } static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); -static int acpi_start_single_object(struct acpi_device *); static int acpi_device_probe(struct device * dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -470,15 +638,13 @@ static int acpi_device_probe(struct device * dev) ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) - acpi_start_single_object(acpi_dev); - if (acpi_drv->ops.notify) { ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, - acpi_dev->removal_type); + acpi_drv->ops.remove(acpi_dev); + acpi_dev->driver = NULL; + acpi_dev->driver_data = NULL; return ret; } } @@ -500,7 +666,7 @@ static int acpi_device_remove(struct device * dev) if (acpi_drv->ops.notify) acpi_device_remove_notify_handler(acpi_dev); if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); + acpi_drv->ops.remove(acpi_dev); } acpi_dev->driver = NULL; acpi_dev->driver_data = NULL; @@ -517,12 +683,25 @@ struct bus_type acpi_bus_type = { .uevent = acpi_device_uevent, }; -static int acpi_device_register(struct acpi_device *device) +int acpi_device_add(struct acpi_device *device, + void (*release)(struct device *)) { int result; struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; int found = 0; + if (device->handle) { + acpi_status status; + + status = acpi_attach_data(device->handle, acpi_bus_data_handler, + device); + if (ACPI_FAILURE(status)) { + acpi_handle_err(device->handle, + "Unable to attach device data\n"); + return -ENODEV; + } + } + /* * Linkage * ------- @@ -533,11 +712,13 @@ static int acpi_device_register(struct acpi_device *device) INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); mutex_init(&device->physical_node_lock); + INIT_LIST_HEAD(&device->power_dependent); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); if (!new_bus_id) { - printk(KERN_ERR PREFIX "Memory allocation error\n"); - return -ENOMEM; + pr_err(PREFIX "Memory allocation error\n"); + result = -ENOMEM; + goto err_detach; } mutex_lock(&acpi_device_lock); @@ -572,11 +753,11 @@ static int acpi_device_register(struct acpi_device *device) if (device->parent) device->dev.parent = &device->parent->dev; device->dev.bus = &acpi_bus_type; - device->dev.release = &acpi_device_release; - result = device_register(&device->dev); + device->dev.release = release; + result = device_add(&device->dev); if (result) { dev_err(&device->dev, "Error registering device\n"); - goto end; + goto err; } result = acpi_device_setup_files(device); @@ -586,16 +767,20 @@ static int acpi_device_register(struct acpi_device *device) device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; -end: + + err: mutex_lock(&acpi_device_lock); if (device->parent) list_del(&device->node); list_del(&device->wakeup_list); mutex_unlock(&acpi_device_lock); + + err_detach: + acpi_detach_data(device->handle, acpi_bus_data_handler); return result; } -static void acpi_device_unregister(struct acpi_device *device, int type) +static void acpi_device_unregister(struct acpi_device *device) { mutex_lock(&acpi_device_lock); if (device->parent) @@ -606,8 +791,20 @@ static void acpi_device_unregister(struct acpi_device *device, int type) acpi_detach_data(device->handle, acpi_bus_data_handler); + acpi_power_add_remove_device(device, false); acpi_device_remove_files(device); - device_unregister(&device->dev); + if (device->remove) + device->remove(device); + + device_del(&device->dev); + /* + * Transition the device to D3cold to drop the reference counts of all + * power resources the device depends on and turn off the ones that have + * no more references. + */ + acpi_device_set_power(device, ACPI_STATE_D3_COLD); + device->handle = NULL; + put_device(&device->dev); } /* -------------------------------------------------------------------------- @@ -651,24 +848,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) return 0; } -static int acpi_start_single_object(struct acpi_device *device) -{ - int result = 0; - struct acpi_driver *driver; - - - if (!(driver = device->driver)) - return 0; - - if (driver->ops.start) { - result = driver->ops.start(device); - if (result && driver->ops.remove) - driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - } - - return result; -} - /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered @@ -712,29 +891,23 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver); -------------------------------------------------------------------------- */ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) { + struct acpi_device *device = NULL; acpi_status status; - int ret; - struct acpi_device *device; /* * Fixed hardware devices do not appear in the namespace and do not * have handles, but we fabricate acpi_devices for them, so we have * to deal with them specially. */ - if (handle == NULL) + if (!handle) return acpi_root; do { status = acpi_get_parent(handle, &handle); - if (status == AE_NULL_ENTRY) - return NULL; if (ACPI_FAILURE(status)) - return acpi_root; - - ret = acpi_bus_get_device(handle, &device); - if (ret == 0) - return device; - } while (1); + return status == AE_NULL_ENTRY ? NULL : acpi_root; + } while (acpi_bus_get_device(handle, &device)); + return device; } acpi_status @@ -768,52 +941,43 @@ void acpi_bus_data_handler(acpi_handle handle, void *context) return; } -static int acpi_bus_get_perf_flags(struct acpi_device *device) -{ - device->performance.state = ACPI_STATE_UNKNOWN; - return 0; -} - -static acpi_status -acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, - struct acpi_device_wakeup *wakeup) +static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, + struct acpi_device_wakeup *wakeup) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *package = NULL; union acpi_object *element = NULL; acpi_status status; - int i = 0; + int err = -ENODATA; if (!wakeup) - return AE_BAD_PARAMETER; + return -EINVAL; + + INIT_LIST_HEAD(&wakeup->resources); /* _PRW */ status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); - return status; + return err; } package = (union acpi_object *)buffer.pointer; - if (!package || (package->package.count < 2)) { - status = AE_BAD_DATA; + if (!package || package->package.count < 2) goto out; - } element = &(package->package.elements[0]); - if (!element) { - status = AE_BAD_DATA; + if (!element) goto out; - } + if (element->type == ACPI_TYPE_PACKAGE) { if ((element->package.count < 2) || (element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) - || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) { - status = AE_BAD_DATA; + || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) goto out; - } + wakeup->gpe_device = element->package.elements[0].reference.handle; wakeup->gpe_number = @@ -822,45 +986,49 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, wakeup->gpe_device = NULL; wakeup->gpe_number = element->integer.value; } else { - status = AE_BAD_DATA; goto out; } element = &(package->package.elements[1]); - if (element->type != ACPI_TYPE_INTEGER) { - status = AE_BAD_DATA; + if (element->type != ACPI_TYPE_INTEGER) goto out; - } + wakeup->sleep_state = element->integer.value; - if ((package->package.count - 2) > ACPI_MAX_HANDLES) { - status = AE_NO_MEMORY; + err = acpi_extract_power_resources(package, 2, &wakeup->resources); + if (err) goto out; - } - wakeup->resources.count = package->package.count - 2; - for (i = 0; i < wakeup->resources.count; i++) { - element = &(package->package.elements[i + 2]); - if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { - status = AE_BAD_DATA; + + if (!list_empty(&wakeup->resources)) { + int sleep_state; + + err = acpi_power_wakeup_list_init(&wakeup->resources, + &sleep_state); + if (err) { + acpi_handle_warn(handle, "Retrieving current states " + "of wakeup power resources failed\n"); + acpi_power_resources_list_free(&wakeup->resources); goto out; } - - wakeup->resources.handles[i] = element->reference.handle; + if (sleep_state < wakeup->sleep_state) { + acpi_handle_warn(handle, "Overriding _PRW sleep state " + "(S%d) by S%d from power resources\n", + (int)wakeup->sleep_state, sleep_state); + wakeup->sleep_state = sleep_state; + } } - acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); out: kfree(buffer.pointer); - - return status; + return err; } static void acpi_bus_set_run_wake_flags(struct acpi_device *device) { struct acpi_device_id button_device_ids[] = { - {"PNP0C0D", 0}, {"PNP0C0C", 0}, + {"PNP0C0D", 0}, {"PNP0C0E", 0}, {"", 0}, }; @@ -872,6 +1040,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) { device->wakeup.flags.run_wake = 1; + if (!acpi_match_device_ids(device, &button_device_ids[1])) { + /* Do not use Lid/sleep button for S5 wakeup */ + if (device->wakeup.sleep_state == ACPI_STATE_S5) + device->wakeup.sleep_state = ACPI_STATE_S4; + } device_set_wakeup_capable(&device->dev, true); return; } @@ -888,17 +1061,17 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) { acpi_handle temp; acpi_status status = 0; - int psw_error; + int err; /* Presence of _PRW indicates wake capable */ status = acpi_get_handle(device->handle, "_PRW", &temp); if (ACPI_FAILURE(status)) return; - status = acpi_bus_extract_wakeup_device_power_package(device->handle, - &device->wakeup); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); + err = acpi_bus_extract_wakeup_device_power_package(device->handle, + &device->wakeup); + if (err) { + dev_err(&device->dev, "_PRW evaluation error: %d\n", err); return; } @@ -911,20 +1084,73 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) * So it is necessary to call _DSW object first. Only when it is not * present will the _PSW object used. */ - psw_error = acpi_device_sleep_wake(device, 0, 0, 0); - if (psw_error) + err = acpi_device_sleep_wake(device, 0, 0, 0); + if (err) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in _DSW or _PSW evaluation\n")); } -static void acpi_bus_add_power_resource(acpi_handle handle); +static void acpi_bus_init_power_state(struct acpi_device *device, int state) +{ + struct acpi_device_power_state *ps = &device->power.states[state]; + char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' }; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_handle handle; + acpi_status status; + + INIT_LIST_HEAD(&ps->resources); -static int acpi_bus_get_power_flags(struct acpi_device *device) + /* Evaluate "_PRx" to get referenced power resources */ + status = acpi_evaluate_object(device->handle, pathname, NULL, &buffer); + if (ACPI_SUCCESS(status)) { + union acpi_object *package = buffer.pointer; + + if (buffer.length && package + && package->type == ACPI_TYPE_PACKAGE + && package->package.count) { + int err = acpi_extract_power_resources(package, 0, + &ps->resources); + if (!err) + device->power.flags.power_resources = 1; + } + ACPI_FREE(buffer.pointer); + } + + /* Evaluate "_PSx" to see if we can do explicit sets */ + pathname[2] = 'S'; + status = acpi_get_handle(device->handle, pathname, &handle); + if (ACPI_SUCCESS(status)) + ps->flags.explicit_set = 1; + + /* + * State is valid if there are means to put the device into it. + * D3hot is only valid if _PR3 present. + */ + if (!list_empty(&ps->resources) + || (ps->flags.explicit_set && state < ACPI_STATE_D3_HOT)) { + ps->flags.valid = 1; + ps->flags.os_accessible = 1; + } + + ps->power = -1; /* Unknown - driver assigned */ + ps->latency = -1; /* Unknown - driver assigned */ +} + +static void acpi_bus_get_power_flags(struct acpi_device *device) { - acpi_status status = 0; - acpi_handle handle = NULL; - u32 i = 0; + acpi_status status; + acpi_handle handle; + u32 i; + /* Presence of _PS0|_PR0 indicates 'power manageable' */ + status = acpi_get_handle(device->handle, "_PS0", &handle); + if (ACPI_FAILURE(status)) { + status = acpi_get_handle(device->handle, "_PR0", &handle); + if (ACPI_FAILURE(status)) + return; + } + + device->flags.power_manageable = 1; /* * Power Management Flags @@ -939,38 +1165,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) /* * Enumerate supported power management states */ - for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { - struct acpi_device_power_state *ps = &device->power.states[i]; - char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; - - /* Evaluate "_PRx" to se if power resources are referenced */ - acpi_evaluate_reference(device->handle, object_name, NULL, - &ps->resources); - if (ps->resources.count) { - int j; - - device->power.flags.power_resources = 1; - for (j = 0; j < ps->resources.count; j++) - acpi_bus_add_power_resource(ps->resources.handles[j]); - } - - /* Evaluate "_PSx" to see if we can do explicit sets */ - object_name[2] = 'S'; - status = acpi_get_handle(device->handle, object_name, &handle); - if (ACPI_SUCCESS(status)) - ps->flags.explicit_set = 1; - - /* - * State is valid if there are means to put the device into it. - * D3hot is only valid if _PR3 present. - */ - if (ps->resources.count || - (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) - ps->flags.valid = 1; + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) + acpi_bus_init_power_state(device, i); - ps->power = -1; /* Unknown - driver assigned */ - ps->latency = -1; /* Unknown - driver assigned */ - } + INIT_LIST_HEAD(&device->power.states[ACPI_STATE_D3_COLD].resources); /* Set defaults for D0 and D3 states (always valid) */ device->power.states[ACPI_STATE_D0].flags.valid = 1; @@ -982,17 +1180,22 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set) device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1; - acpi_bus_init_power(device); + /* Presence of _PS3 or _PRx means we can put the device into D3 cold */ + if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set || + device->power.flags.power_resources) + device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; - return 0; + if (acpi_bus_init_power(device)) { + acpi_free_power_resources_lists(device); + device->flags.power_manageable = 0; + } } -static int acpi_bus_get_flags(struct acpi_device *device) +static void acpi_bus_get_flags(struct acpi_device *device) { acpi_status status = AE_OK; acpi_handle temp = NULL; - /* Presence of _STA indicates 'dynamic_status' */ status = acpi_get_handle(device->handle, "_STA", &temp); if (ACPI_SUCCESS(status)) @@ -1012,26 +1215,6 @@ static int acpi_bus_get_flags(struct acpi_device *device) if (ACPI_SUCCESS(status)) device->flags.ejectable = 1; } - - /* Presence of _LCK indicates 'lockable' */ - status = acpi_get_handle(device->handle, "_LCK", &temp); - if (ACPI_SUCCESS(status)) - device->flags.lockable = 1; - - /* Power resources cannot be power manageable. */ - if (device->device_type == ACPI_BUS_TYPE_POWER) - return 0; - - /* Presence of _PS0|_PR0 indicates 'power manageable' */ - status = acpi_get_handle(device->handle, "_PS0", &temp); - if (ACPI_FAILURE(status)) - status = acpi_get_handle(device->handle, "_PR0", &temp); - if (ACPI_SUCCESS(status)) - device->flags.power_manageable = 1; - - /* TBD: Performance management */ - - return 0; } static void acpi_device_get_busid(struct acpi_device *device) @@ -1185,7 +1368,7 @@ static void acpi_device_set_id(struct acpi_device *device) { acpi_status status; struct acpi_device_info *info; - struct acpica_device_id_list *cid_list; + struct acpi_pnp_device_id_list *cid_list; int i; switch (device->device_type) { @@ -1212,6 +1395,9 @@ static void acpi_device_set_id(struct acpi_device *device) device->pnp.bus_address = info->address; device->flags.bus_address = 1; } + if (info->valid & ACPI_VALID_UID) + device->pnp.unique_id = kstrdup(info->unique_id.string, + GFP_KERNEL); kfree(info); @@ -1227,7 +1413,7 @@ static void acpi_device_set_id(struct acpi_device *device) acpi_add_id(device, ACPI_DOCK_HID); else if (!acpi_ibm_smbus_match(device)) acpi_add_id(device, ACPI_SMBUS_IBM_HID); - else if (!acpi_device_hid(device) && + else if (list_empty(&device->pnp.ids) && ACPI_IS_ROOT_DEVICE(device->parent)) { acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); @@ -1253,56 +1439,32 @@ static void acpi_device_set_id(struct acpi_device *device) } } -static int acpi_device_set_context(struct acpi_device *device) +void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, + int type, unsigned long long sta) { - acpi_status status; - - /* - * Context - * ------- - * Attach this 'struct acpi_device' to the ACPI object. This makes - * resolutions from handle->device very efficient. Fixed hardware - * devices have no handles, so we skip them. - */ - if (!device->handle) - return 0; - - status = acpi_attach_data(device->handle, - acpi_bus_data_handler, device); - if (ACPI_SUCCESS(status)) - return 0; - - printk(KERN_ERR PREFIX "Error attaching device data\n"); - return -ENODEV; + INIT_LIST_HEAD(&device->pnp.ids); + device->device_type = type; + device->handle = handle; + device->parent = acpi_bus_get_parent(handle); + STRUCT_TO_INT(device->status) = sta; + acpi_device_get_busid(device); + acpi_device_set_id(device); + acpi_bus_get_flags(device); + device->flags.match_driver = false; + device_initialize(&device->dev); + dev_set_uevent_suppress(&device->dev, true); } -static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) +void acpi_device_add_finalize(struct acpi_device *device) { - if (!dev) - return -EINVAL; - - dev->removal_type = ACPI_BUS_REMOVAL_EJECT; - device_release_driver(&dev->dev); - - if (!rmdevice) - return 0; - - /* - * unbind _ADR-Based Devices when hot removal - */ - if (dev->flags.bus_address) { - if ((dev->parent) && (dev->parent->ops.unbind)) - dev->parent->ops.unbind(dev); - } - acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT); - - return 0; + device->flags.match_driver = true; + dev_set_uevent_suppress(&device->dev, false); + kobject_uevent(&device->dev.kobj, KOBJ_ADD); } static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, - unsigned long long sta, - struct acpi_bus_ops *ops) + unsigned long long sta) { int result; struct acpi_device *device; @@ -1314,102 +1476,25 @@ static int acpi_add_single_object(struct acpi_device **child, return -ENOMEM; } - INIT_LIST_HEAD(&device->pnp.ids); - device->device_type = type; - device->handle = handle; - device->parent = acpi_bus_get_parent(handle); - device->bus_ops = *ops; /* workround for not call .start */ - STRUCT_TO_INT(device->status) = sta; - - acpi_device_get_busid(device); - - /* - * Flags - * ----- - * Note that we only look for object handles -- cannot evaluate objects - * until we know the device is present and properly initialized. - */ - result = acpi_bus_get_flags(device); - if (result) - goto end; - - /* - * Initialize Device - * ----------------- - * TBD: Synch with Core's enumeration/initialization process. - */ - acpi_device_set_id(device); - - /* - * Power Management - * ---------------- - */ - if (device->flags.power_manageable) { - result = acpi_bus_get_power_flags(device); - if (result) - goto end; - } - - /* - * Wakeup device management - *----------------------- - */ + acpi_init_device_object(device, handle, type, sta); + acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); - /* - * Performance Management - * ---------------------- - */ - if (device->flags.performance_manageable) { - result = acpi_bus_get_perf_flags(device); - if (result) - goto end; - } - - if ((result = acpi_device_set_context(device))) - goto end; - - result = acpi_device_register(device); - - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } - -end: - if (!result) { - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Adding %s [%s] parent %s\n", dev_name(&device->dev), - (char *) buffer.pointer, - device->parent ? dev_name(&device->parent->dev) : - "(null)")); - kfree(buffer.pointer); - *child = device; - } else + result = acpi_device_add(device, acpi_device_release); + if (result) { acpi_device_release(&device->dev); + return result; + } - return result; -} - -#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ - ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) - -static void acpi_bus_add_power_resource(acpi_handle handle) -{ - struct acpi_bus_ops ops = { - .acpi_op_add = 1, - .acpi_op_start = 1, - }; - struct acpi_device *device = NULL; - - acpi_bus_get_device(handle, &device); - if (!device) - acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, &ops); + acpi_power_add_remove_device(device, true); + acpi_device_add_finalize(device); + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n", + dev_name(&device->dev), (char *) buffer.pointer, + device->parent ? dev_name(&device->parent->dev) : "(null)")); + kfree(buffer.pointer); + *child = device; + return 0; } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1451,213 +1536,248 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, return 0; } -static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, - void *context, void **return_value) +static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **return_value) { - struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; + acpi_bus_get_device(handle, &device); + if (device) + goto out; + result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; + if (type == ACPI_BUS_TYPE_POWER) { + acpi_add_power_resource(handle); + return AE_OK; + } + if (!(sta & ACPI_STA_DEVICE_PRESENT) && !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { struct acpi_device_wakeup wakeup; acpi_handle temp; status = acpi_get_handle(handle, "_PRW", &temp); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(status)) { acpi_bus_extract_wakeup_device_power_package(handle, &wakeup); + acpi_power_resources_list_free(&wakeup.resources); + } return AE_CTRL_DEPTH; } - /* - * We may already have an acpi_device from a previous enumeration. If - * so, we needn't add it again, but we may still have to start it. - */ - device = NULL; - acpi_bus_get_device(handle, &device); - if (ops->acpi_op_add && !device) - acpi_add_single_object(&device, handle, type, sta, ops); - + acpi_add_single_object(&device, handle, type, sta); if (!device) return AE_CTRL_DEPTH; - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) - return AE_CTRL_DEPTH; - } - + out: if (!*return_value) *return_value = device; + return AE_OK; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, - struct acpi_device **child) +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id) { - acpi_status status; - void *device = NULL; + struct acpi_scan_handler *handler; - status = acpi_bus_check_add(handle, 0, ops, &device); - if (ACPI_SUCCESS(status)) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { + const struct acpi_device_id *devid; - if (child) - *child = device; + for (devid = handler->ids; devid->id[0]; devid++) { + int ret; - if (device) - return 0; - else - return -ENODEV; -} + if (strcmp((char *)devid->id, id)) + continue; -/* - * acpi_bus_add and acpi_bus_start - * - * scan a given ACPI tree and (probably recently hot-plugged) - * create and add or starts found devices. - * - * If no devices were found -ENODEV is returned which does not - * mean that this is a real error, there just have been no suitable - * ACPI objects in the table trunk from which the kernel could create - * a device and add/start an appropriate driver. - */ + ret = handler->attach(device, devid); + if (ret > 0) { + device->handler = handler; + return ret; + } else if (ret < 0) { + return ret; + } + } + } + return 0; +} -int -acpi_bus_add(struct acpi_device **child, - struct acpi_device *parent, acpi_handle handle, int type) +static int acpi_scan_attach_handler(struct acpi_device *device) { - struct acpi_bus_ops ops; + struct acpi_hardware_id *hwid; + int ret = 0; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + list_for_each_entry(hwid, &device->pnp.ids, list) { + ret = acpi_scan_do_attach_handler(device, hwid->id); + if (ret) + break; - return acpi_bus_scan(handle, &ops, child); + } + return ret; } -EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; - - if (!device) - return -EINVAL; + struct acpi_device *device; + unsigned long long sta_not_used; + int ret; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) + return AE_OK; - result = acpi_bus_scan(device->handle, &ops, NULL); + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; - acpi_update_all_gpes(); + ret = acpi_scan_attach_handler(device); + if (ret) + return ret > 0 ? AE_OK : AE_CTRL_DEPTH; - return result; + ret = device_attach(&device->dev); + return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; } -EXPORT_SYMBOL(acpi_bus_start); -int acpi_bus_trim(struct acpi_device *start, int rmdevice) +/** + * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. + * @handle: Root of the namespace scope to scan. + * + * Scan a given ACPI tree (probably recently hot-plugged) and create and add + * found devices. + * + * If no devices were found, -ENODEV is returned, but it does not mean that + * there has been a real error. There just have been no suitable ACPI objects + * in the table trunk from which the kernel could create a device and add an + * appropriate driver. + * + * Must be called under acpi_scan_lock. + */ +int acpi_bus_scan(acpi_handle handle) { - acpi_status status; - struct acpi_device *parent, *child; - acpi_handle phandle, chandle; - acpi_object_type type; - u32 level = 1; - int err = 0; + void *device = NULL; + int error = 0; - parent = start; - phandle = start->handle; - child = chandle = NULL; + if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_check_add, NULL, NULL, &device); - while ((level > 0) && parent && (!err)) { - status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, - chandle, &chandle); + if (!device) + error = -ENODEV; + else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_device_attach, NULL, NULL, NULL); - /* - * If this scope is exhausted then move our way back up. - */ - if (ACPI_FAILURE(status)) { - level--; - chandle = phandle; - acpi_get_parent(phandle, &phandle); - child = parent; - parent = parent->parent; - - if (level == 0) - err = acpi_bus_remove(child, rmdevice); - else - err = acpi_bus_remove(child, 1); + return error; +} +EXPORT_SYMBOL(acpi_bus_scan); - continue; - } +static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) +{ + struct acpi_device *device = NULL; - status = acpi_get_type(chandle, &type); - if (ACPI_FAILURE(status)) { - continue; - } - /* - * If there is a device corresponding to chandle then - * parse it (depth-first). - */ - if (acpi_bus_get_device(chandle, &child) == 0) { - level++; - phandle = chandle; - chandle = NULL; - parent = child; + if (!acpi_bus_get_device(handle, &device)) { + struct acpi_scan_handler *dev_handler = device->handler; + + device->removal_type = ACPI_BUS_REMOVAL_EJECT; + if (dev_handler) { + if (dev_handler->detach) + dev_handler->detach(device); + + device->handler = NULL; + } else { + device_release_driver(&device->dev); } - continue; } - return err; + return AE_OK; +} + +static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) +{ + struct acpi_device *device = NULL; + + if (!acpi_bus_get_device(handle, &device)) + acpi_device_unregister(device); + + return AE_OK; +} + +/** + * acpi_bus_trim - Remove ACPI device node and all of its descendants + * @start: Root of the ACPI device nodes subtree to remove. + * + * Must be called under acpi_scan_lock. + */ +void acpi_bus_trim(struct acpi_device *start) +{ + /* + * Execute acpi_bus_device_detach() as a post-order callback to detach + * all ACPI drivers from the device nodes being removed. + */ + acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, + acpi_bus_device_detach, NULL, NULL); + acpi_bus_device_detach(start->handle, 0, NULL, NULL); + /* + * Execute acpi_bus_remove() as a post-order callback to remove device + * nodes in the given namespace scope. + */ + acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, + acpi_bus_remove, NULL, NULL); + acpi_bus_remove(start->handle, 0, NULL, NULL); } EXPORT_SYMBOL_GPL(acpi_bus_trim); static int acpi_bus_scan_fixed(void) { int result = 0; - struct acpi_device *device = NULL; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; /* * Enumerate all fixed-feature devices. */ - if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { + struct acpi_device *device = NULL; + result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT, - &ops); + ACPI_STA_DEFAULT); + if (result) + return result; + + result = device_attach(&device->dev); + if (result < 0) + return result; + device_init_wakeup(&device->dev, true); } - if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { + if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) { + struct acpi_device *device = NULL; + result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT, - &ops); + ACPI_STA_DEFAULT); + if (result) + return result; + + result = device_attach(&device->dev); } - return result; + return result < 0 ? result : 0; } int __init acpi_scan_init(void) { int result; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1665,20 +1785,36 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); } - acpi_power_init(); + acpi_pci_root_init(); + acpi_pci_link_init(); + acpi_platform_init(); + acpi_csrt_init(); + acpi_container_init(); + acpi_pci_slot_init(); + mutex_lock(&acpi_scan_lock); /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); - - if (!result) - result = acpi_bus_scan_fixed(); + result = acpi_bus_scan(ACPI_ROOT_OBJECT); + if (result) + goto out; + result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); if (result) - acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); - else - acpi_update_all_gpes(); + goto out; + result = acpi_bus_scan_fixed(); + if (result) { + acpi_device_unregister(acpi_root); + goto out; + } + + acpi_update_all_gpes(); + + acpi_pci_root_hp_init(); + + out: + mutex_unlock(&acpi_scan_lock); return result; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index fdcdbb652915..24213033fbae 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -18,7 +18,6 @@ #include <linux/reboot.h> #include <linux/acpi.h> #include <linux/module.h> -#include <linux/pm_runtime.h> #include <asm/io.h> @@ -81,6 +80,12 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; + +u32 acpi_target_system_state(void) +{ + return acpi_target_sleep_state; +} + static bool pwr_btn_event_pending; /* @@ -98,6 +103,21 @@ void __init acpi_nvs_nosave(void) } /* + * The ACPI specification wants us to save NVS memory regions during hibernation + * but says nothing about saving NVS during S3. Not all versions of Windows + * save NVS on S3 suspend either, and it is clear that not all systems need + * NVS to be saved at S3 time. To improve suspend/resume time, allow the + * user to disable saving NVS on S3 if their system does not require it, but + * continue to save/restore NVS for S4 as specified. + */ +static bool nvs_nosave_s3; + +void __init acpi_nvs_nosave_s3(void) +{ + nvs_nosave_s3 = true; +} + +/* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' * kernel command line option that causes the following variable to be set. @@ -109,6 +129,188 @@ void __init acpi_old_suspend_ordering(void) old_suspend_ordering = true; } +static int __init init_old_suspend_ordering(const struct dmi_system_id *d) +{ + acpi_old_suspend_ordering(); + return 0; +} + +static int __init init_nvs_nosave(const struct dmi_system_id *d) +{ + acpi_nvs_nosave(); + return 0; +} + +static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + { + .callback = init_old_suspend_ordering, + .ident = "Abit KN9 (nForce4 variant)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), + DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Panasonic CF51-2L", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, + "Matsushita Electric Industrial Co.,Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW41E_H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW21E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB17FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Everex StepNote Series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1Z1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-NW130D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCCW29FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Averatec AV1020-ED2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), + DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI DELUXE", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI Premium", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR26GN_P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1S1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW520F", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Asus K54C", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K54C"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Asus K54HR", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), + }, + }, + {}, +}; + +static void acpi_sleep_dmi_check(void) +{ + dmi_check_system(acpisleep_dmi_table); +} + /** * acpi_pm_freeze - Disable the GPEs and suspend EC transactions. */ @@ -192,6 +394,8 @@ static void acpi_pm_finish(void) acpi_target_sleep_state = ACPI_STATE_S0; + acpi_resume_power_resources(); + /* If we were woken with the fixed power button, provide a small * hint to userspace in the form of a wakeup event on the fixed power * button device (if it can be found). @@ -224,6 +428,7 @@ static void acpi_pm_end(void) } #else /* !CONFIG_ACPI_SLEEP */ #define acpi_target_sleep_state ACPI_STATE_S0 +static inline void acpi_sleep_dmi_check(void) {} #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND @@ -243,7 +448,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state) u32 acpi_state = acpi_suspend_states[pm_state]; int error = 0; - error = nvs_nosave ? 0 : suspend_nvs_alloc(); + error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc(); if (error) return error; @@ -383,167 +588,26 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { .recover = acpi_pm_finish, }; -static int __init init_old_suspend_ordering(const struct dmi_system_id *d) +static void acpi_sleep_suspend_setup(void) { - old_suspend_ordering = true; - return 0; -} + int i; -static int __init init_nvs_nosave(const struct dmi_system_id *d) -{ - acpi_nvs_nosave(); - return 0; -} + for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { + acpi_status status; + u8 type_a, type_b; -static struct dmi_system_id __initdata acpisleep_dmi_table[] = { - { - .callback = init_old_suspend_ordering, - .ident = "Abit KN9 (nForce4 variant)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), - DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "HP xw4600 Workstation", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Panasonic CF51-2L", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, - "Matsushita Electric Industrial Co.,Ltd."), - DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-FW21E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB17FX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR11M", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Everex StepNote Series", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB1Z1E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-NW130D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCCW29FX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Averatec AV1020-ED2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), - DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus A8N-SLI DELUXE", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus A8N-SLI Premium", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR26GN_P", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-FW520F", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Asus K54C", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K54C"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Asus K54HR", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), - }, - }, - {}, -}; -#endif /* CONFIG_SUSPEND */ + status = acpi_get_sleep_type_data(i, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + sleep_states[i] = 1; + } + } + + suspend_set_ops(old_suspend_ordering ? + &acpi_suspend_ops_old : &acpi_suspend_ops); +} +#else /* !CONFIG_SUSPEND */ +static inline void acpi_sleep_suspend_setup(void) {} +#endif /* !CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION static unsigned long s4_hardware_signature; @@ -664,7 +728,29 @@ static const struct platform_hibernation_ops acpi_hibernation_ops_old = { .restore_cleanup = acpi_pm_thaw, .recover = acpi_pm_finish, }; -#endif /* CONFIG_HIBERNATION */ + +static void acpi_sleep_hibernate_setup(void) +{ + acpi_status status; + u8 type_a, type_b; + + status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); + if (ACPI_FAILURE(status)) + return; + + hibernation_set_ops(old_suspend_ordering ? + &acpi_hibernation_ops_old : &acpi_hibernation_ops); + sleep_states[ACPI_STATE_S4] = 1; + if (nosigcheck) + return; + + acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs); + if (facs) + s4_hardware_signature = facs->hardware_signature; +} +#else /* !CONFIG_HIBERNATION */ +static inline void acpi_sleep_hibernate_setup(void) {} +#endif /* !CONFIG_HIBERNATION */ int acpi_suspend(u32 acpi_state) { @@ -681,177 +767,6 @@ int acpi_suspend(u32 acpi_state) return -EINVAL; } -#ifdef CONFIG_PM -/** - * acpi_pm_device_sleep_state - return preferred power state of ACPI device - * in the system sleep state given by %acpi_target_sleep_state - * @dev: device to examine; its driver model wakeup flags control - * whether it should be able to wake up the system - * @d_min_p: used to store the upper limit of allowed states range - * @d_max_in: specify the lowest allowed states - * Return value: preferred power state of the device on success, -ENODEV - * (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure - * - * Find the lowest power (highest number) ACPI device power state that - * device @dev can be in while the system is in the sleep state represented - * by %acpi_target_sleep_state. If @wake is nonzero, the device should be - * able to wake up the system from this sleep state. If @d_min_p is set, - * the highest power (lowest number) device power state of @dev allowed - * in this system sleep state is stored at the location pointed to by it. - * - * The caller must ensure that @dev is valid before using this function. - * The caller is also responsible for figuring out if the device is - * supposed to be able to wake up the system and passing this information - * via @wake. - */ - -int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) -{ - acpi_handle handle = DEVICE_ACPI_HANDLE(dev); - struct acpi_device *adev; - char acpi_method[] = "_SxD"; - unsigned long long d_min, d_max; - - if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3) - return -EINVAL; - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { - printk(KERN_DEBUG "ACPI handle has no context!\n"); - return -ENODEV; - } - - acpi_method[2] = '0' + acpi_target_sleep_state; - /* - * If the sleep state is S0, the lowest limit from ACPI is D3, - * but if the device has _S0W, we will use the value from _S0W - * as the lowest limit from ACPI. Finally, we will constrain - * the lowest limit with the specified one. - */ - d_min = ACPI_STATE_D0; - d_max = ACPI_STATE_D3; - - /* - * If present, _SxD methods return the minimum D-state (highest power - * state) we can use for the corresponding S-states. Otherwise, the - * minimum D-state is D0 (ACPI 3.x). - * - * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer - * provided -- that's our fault recovery, we ignore retval. - */ - if (acpi_target_sleep_state > ACPI_STATE_S0) - acpi_evaluate_integer(handle, acpi_method, NULL, &d_min); - - /* - * If _PRW says we can wake up the system from the target sleep state, - * the D-state returned by _SxD is sufficient for that (we assume a - * wakeup-aware driver if wake is set). Still, if _SxW exists - * (ACPI 3.x), it should return the maximum (lowest power) D-state that - * can wake the system. _S0W may be valid, too. - */ - if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.flags.valid && - adev->wakeup.sleep_state >= acpi_target_sleep_state)) { - acpi_status status; - - acpi_method[3] = 'W'; - status = acpi_evaluate_integer(handle, acpi_method, NULL, - &d_max); - if (ACPI_FAILURE(status)) { - if (acpi_target_sleep_state != ACPI_STATE_S0 || - status != AE_NOT_FOUND) - d_max = d_min; - } else if (d_max < d_min) { - /* Warn the user of the broken DSDT */ - printk(KERN_WARNING "ACPI: Wrong value from %s\n", - acpi_method); - /* Sanitize it */ - d_min = d_max; - } - } - - if (d_max_in < d_min) - return -EINVAL; - if (d_min_p) - *d_min_p = d_min; - /* constrain d_max with specified lowest limit (max number) */ - if (d_max > d_max_in) { - for (d_max = d_max_in; d_max > d_min; d_max--) { - if (adev->power.states[d_max].flags.valid) - break; - } - } - return d_max; -} -EXPORT_SYMBOL(acpi_pm_device_sleep_state); -#endif /* CONFIG_PM */ - -#ifdef CONFIG_PM_SLEEP -/** - * acpi_pm_device_run_wake - Enable/disable wake-up for given device. - * @phys_dev: Device to enable/disable the platform to wake-up the system for. - * @enable: Whether enable or disable the wake-up functionality. - * - * Find the ACPI device object corresponding to @pci_dev and try to - * enable/disable the GPE associated with it. - */ -int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) -{ - struct acpi_device *dev; - acpi_handle handle; - - if (!device_run_wake(phys_dev)) - return -EINVAL; - - handle = DEVICE_ACPI_HANDLE(phys_dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { - dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", - __func__); - return -ENODEV; - } - - if (enable) { - acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); - acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); - } else { - acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); - acpi_disable_wakeup_device_power(dev); - } - - return 0; -} -EXPORT_SYMBOL(acpi_pm_device_run_wake); - -/** - * acpi_pm_device_sleep_wake - enable or disable the system wake-up - * capability of given device - * @dev: device to handle - * @enable: 'true' - enable, 'false' - disable the wake-up capability - */ -int acpi_pm_device_sleep_wake(struct device *dev, bool enable) -{ - acpi_handle handle; - struct acpi_device *adev; - int error; - - if (!device_can_wakeup(dev)) - return -EINVAL; - - handle = DEVICE_ACPI_HANDLE(dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { - dev_dbg(dev, "ACPI handle has no context in %s!\n", __func__); - return -ENODEV; - } - - error = enable ? - acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : - acpi_disable_wakeup_device_power(adev); - if (!error) - dev_info(dev, "wake-up capability %s by ACPI\n", - enable ? "enabled" : "disabled"); - - return error; -} -#endif /* CONFIG_PM_SLEEP */ - static void acpi_power_off_prepare(void) { /* Prepare to power off the system */ @@ -871,55 +786,34 @@ int __init acpi_sleep_init(void) { acpi_status status; u8 type_a, type_b; -#ifdef CONFIG_SUSPEND - int i = 0; - - dmi_check_system(acpisleep_dmi_table); -#endif + char supported[ACPI_S_STATE_COUNT * 3 + 1]; + char *pos = supported; + int i; if (acpi_disabled) return 0; - sleep_states[ACPI_STATE_S0] = 1; - printk(KERN_INFO PREFIX "(supports S0"); + acpi_sleep_dmi_check(); -#ifdef CONFIG_SUSPEND - for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { - status = acpi_get_sleep_type_data(i, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - sleep_states[i] = 1; - printk(KERN_CONT " S%d", i); - } - } + sleep_states[ACPI_STATE_S0] = 1; - suspend_set_ops(old_suspend_ordering ? - &acpi_suspend_ops_old : &acpi_suspend_ops); -#endif + acpi_sleep_suspend_setup(); + acpi_sleep_hibernate_setup(); -#ifdef CONFIG_HIBERNATION - status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - hibernation_set_ops(old_suspend_ordering ? - &acpi_hibernation_ops_old : &acpi_hibernation_ops); - sleep_states[ACPI_STATE_S4] = 1; - printk(KERN_CONT " S4"); - if (!nosigcheck) { - acpi_get_table(ACPI_SIG_FACS, 1, - (struct acpi_table_header **)&facs); - if (facs) - s4_hardware_signature = - facs->hardware_signature; - } - } -#endif status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); if (ACPI_SUCCESS(status)) { sleep_states[ACPI_STATE_S5] = 1; - printk(KERN_CONT " S5"); pm_power_off_prepare = acpi_power_off_prepare; pm_power_off = acpi_power_off; } - printk(KERN_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. diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index 74d59c8f4678..0143540a2519 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h @@ -6,3 +6,5 @@ extern void acpi_disable_wakeup_devices(u8 sleep_state); extern struct list_head acpi_wakeup_device_list; extern struct mutex acpi_device_lock; + +extern void acpi_resume_power_resources(void); diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 7c3f98ba4afe..41c0504470db 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -476,7 +476,7 @@ static void fixed_event_count(u32 event_number) return; } -static void acpi_gbl_event_handler(u32 event_type, acpi_handle device, +static void acpi_global_event_handler(u32 event_type, acpi_handle device, u32 event_number, void *context) { if (event_type == ACPI_EVENT_TYPE_GPE) @@ -498,7 +498,7 @@ static int get_status(u32 index, acpi_event_status *status, result = acpi_get_gpe_device(index, handle); if (result) { ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, - "Invalid GPE 0x%x\n", index)); + "Invalid GPE 0x%x", index)); goto end; } result = acpi_get_gpe_status(*handle, index, status); @@ -638,7 +638,7 @@ void acpi_irq_stats_init(void) if (all_counters == NULL) goto fail; - status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL); + status = acpi_install_global_event_handler(acpi_global_event_handler, NULL); if (ACPI_FAILURE(status)) goto fail; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 2572d9715bda..d67a1fe07f0e 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -204,7 +204,7 @@ int __init acpi_table_parse_entries(char *id, unsigned long table_size, int entry_id, - acpi_table_entry_handler handler, + acpi_tbl_entry_handler handler, unsigned int max_entries) { struct acpi_table_header *table_header = NULL; @@ -269,7 +269,7 @@ err: int __init acpi_table_parse_madt(enum acpi_madt_type id, - acpi_table_entry_handler handler, unsigned int max_entries) + acpi_tbl_entry_handler handler, unsigned int max_entries) { return acpi_table_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt), id, @@ -285,7 +285,7 @@ acpi_table_parse_madt(enum acpi_madt_type id, * Scan the ACPI System Descriptor Table (STD) for a table matching @id, * run @handler on it. Return 0 if table found, return on if not. */ -int __init acpi_table_parse(char *id, acpi_table_handler handler) +int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler) { struct acpi_table_header *table = NULL; acpi_size tbl_size; diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 804204d41999..8470771e5eae 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -97,7 +97,7 @@ module_param(psv, int, 0644); MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static int acpi_thermal_add(struct acpi_device *device); -static int acpi_thermal_remove(struct acpi_device *device, int type); +static int acpi_thermal_remove(struct acpi_device *device); static void acpi_thermal_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id thermal_device_ids[] = { @@ -288,7 +288,7 @@ do { \ if (flags != ACPI_TRIPS_INIT) \ ACPI_EXCEPTION((AE_INFO, AE_ERROR, \ "ACPI thermal trip point %s changed\n" \ - "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \ + "Please send acpidump to linux-acpi@vger.kernel.org", str)); \ } while (0) static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) @@ -531,6 +531,10 @@ static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; + if (!tz->tz_enabled) { + pr_warn("thermal zone is disabled \n"); + return; + } thermal_zone_device_update(tz->thermal_zone); } @@ -900,14 +904,14 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) if (tz->trips.passive.flags.valid) tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz, - &acpi_thermal_zone_ops, + &acpi_thermal_zone_ops, NULL, tz->trips.passive.tsp*100, tz->polling_frequency*100); else tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz, - &acpi_thermal_zone_ops, 0, - tz->polling_frequency*100); + &acpi_thermal_zone_ops, NULL, + 0, tz->polling_frequency*100); if (IS_ERR(tz->thermal_zone)) return -ENODEV; @@ -984,6 +988,38 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event) } } +/* + * On some platforms, the AML code has dependency about + * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx. + * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after + * /_CRT/_HOT/_PSV/_ACx, or else system will be power off. + * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0 + * if _TMP has never been evaluated. + * + * As this dependency is totally transparent to OS, evaluate + * all of them once, in the order of _CRT/_HOT/_PSV/_ACx, + * _TMP, before they are actually used. + */ +static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz) +{ + acpi_handle handle = tz->device->handle; + unsigned long long value; + int i; + + acpi_evaluate_integer(handle, "_CRT", NULL, &value); + acpi_evaluate_integer(handle, "_HOT", NULL, &value); + acpi_evaluate_integer(handle, "_PSV", NULL, &value); + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; + acpi_status status; + + status = acpi_evaluate_integer(handle, name, NULL, &value); + if (status == AE_NOT_FOUND) + break; + } + acpi_evaluate_integer(handle, "_TMP", NULL, &value); +} + static int acpi_thermal_get_info(struct acpi_thermal *tz) { int result = 0; @@ -992,6 +1028,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) if (!tz) return -EINVAL; + acpi_thermal_aml_dependency_fix(tz); + /* Get trip points [_CRT, _PSV, etc.] (required) */ result = acpi_thermal_get_trip_points(tz); if (result) @@ -1077,7 +1115,7 @@ end: return result; } -static int acpi_thermal_remove(struct acpi_device *device, int type) +static int acpi_thermal_remove(struct acpi_device *device) { struct acpi_thermal *tz = NULL; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 462f7e300363..744371304313 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -28,6 +28,8 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/types.h> +#include <linux/hardirq.h> +#include <linux/acpi.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -457,3 +459,39 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, #endif } EXPORT_SYMBOL(acpi_evaluate_hotplug_ost); + +/** + * acpi_handle_printk: Print message with ACPI prefix and object path + * + * This function is called through acpi_handle_<level> macros and prints + * a message with ACPI prefix and object path. This function acquires + * the global namespace mutex to obtain an object path. In interrupt + * context, it shows the object path as <n/a>. + */ +void +acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + struct acpi_buffer buffer = { + .length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL + }; + const char *path; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + + if (in_interrupt() || + acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK) + path = "<n/a>"; + else + path = buffer.pointer; + + printk("%sACPI: %s: %pV", level, path, &vaf); + + va_end(args); + kfree(buffer.pointer); +} +EXPORT_SYMBOL(acpi_handle_printk); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 0230cb6cbb3a..313f959413dc 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -88,7 +88,7 @@ module_param(use_bios_initial_backlight, bool, 0644); static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); -static int acpi_video_bus_remove(struct acpi_device *device, int type); +static int acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id video_device_ids[] = { @@ -389,6 +389,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } +static int video_ignore_initial_backlight(const struct dmi_system_id *d) +{ + use_bios_initial_backlight = 0; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -433,6 +439,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP Folio 13-2000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), + }, + }, {} }; @@ -659,7 +673,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) br->levels[i] = br->levels[i - level_ac_battery]; count += level_ac_battery; } else if (level_ac_battery > 2) - ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n")); + ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package")); /* Check if the _BCL package is in a reversed order */ if (max_level == br->levels[2]) { @@ -668,7 +682,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) acpi_video_cmp_level, NULL); } else if (max_level != br->levels[count - 1]) ACPI_ERROR((AE_INFO, - "Found unordered _BCL package\n")); + "Found unordered _BCL package")); br->count = count; device->brightness = br; @@ -1726,7 +1740,7 @@ static int acpi_video_bus_add(struct acpi_device *device) return error; } -static int acpi_video_bus_remove(struct acpi_device *device, int type) +static int acpi_video_bus_remove(struct acpi_device *device) { struct acpi_video_bus *video = NULL; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index b728880ef10e..4ac2593234e7 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -156,6 +156,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "X360"), }, }, + { + .callback = video_detect_force_vendor, + .ident = "Asus UL30VT", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"), + }, + }, { }, }; |