From 683058e315f00a216fd6c79df4f63bc9945ca434 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 3 May 2013 00:26:16 +0200 Subject: ACPI / hotplug: Use device offline/online for graceful hot-removal Modify the generic ACPI hotplug code to be able to check if devices scheduled for hot-removal may be gracefully removed from the system using the device offline/online mechanism introduced previously. Namely, make acpi_scan_hot_remove() handling device hot-removal call device_offline() for all physical companions of the ACPI device nodes involved in the operation and check the results. If any of the device_offline() calls fails, the function will not progress to the removal phase (which cannot be aborted), unless its (new) force argument is set (in case of a failing offline it will put the devices offlined by it back online). In support of 'forced' device hot-removal, add a new sysfs attribute 'force_remove' that will reside under /sys/firmware/acpi/hotplug/. Signed-off-by: Rafael J. Wysocki Reviewed-by: Toshi Kani --- drivers/acpi/internal.h | 2 ++ drivers/acpi/scan.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/sysfs.c | 31 ++++++++++++++++++ 3 files changed, 117 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 6f1afd9118c..4548f0a114c 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -47,6 +47,8 @@ void acpi_memory_hotplug_init(void); static inline void acpi_memory_hotplug_init(void) {} #endif +extern bool acpi_force_hot_remove; + void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, const char *name); int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fe158fd4f1d..4fd392005ef 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -27,6 +27,12 @@ extern struct acpi_device *acpi_root; #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) +/* + * If set, devices will be hot-removed even if they cannot be put offline + * gracefully (from the kernel's standpoint). + */ +bool acpi_force_hot_remove; + static const char *dummy_hid = "device"; static LIST_HEAD(acpi_device_list); @@ -120,6 +126,59 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); +static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, + void *data, void **ret_p) +{ + struct acpi_device *device = NULL; + struct acpi_device_physical_node *pn; + acpi_status status = AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_OK; + + mutex_lock(&device->physical_node_lock); + + list_for_each_entry(pn, &device->physical_node_list, node) { + int ret; + + ret = device_offline(pn->dev); + if (acpi_force_hot_remove) + continue; + + if (ret < 0) { + status = AE_ERROR; + break; + } + pn->put_online = !ret; + } + + mutex_unlock(&device->physical_node_lock); + + return status; +} + +static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, + void *data, void **ret_p) +{ + struct acpi_device *device = NULL; + struct acpi_device_physical_node *pn; + + if (acpi_bus_get_device(handle, &device)) + return AE_OK; + + mutex_lock(&device->physical_node_lock); + + list_for_each_entry(pn, &device->physical_node_list, node) + if (pn->put_online) { + device_online(pn->dev); + pn->put_online = false; + } + + mutex_unlock(&device->physical_node_lock); + + return AE_OK; +} + static int acpi_scan_hot_remove(struct acpi_device *device) { acpi_handle handle = device->handle; @@ -136,10 +195,33 @@ static int acpi_scan_hot_remove(struct acpi_device *device) return -EINVAL; } + lock_device_hotplug(); + + status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + NULL, acpi_bus_offline_companions, NULL, + NULL); + if (ACPI_SUCCESS(status) || acpi_force_hot_remove) + status = acpi_bus_offline_companions(handle, 0, NULL, NULL); + + if (ACPI_FAILURE(status) && !acpi_force_hot_remove) { + acpi_bus_online_companions(handle, 0, NULL, NULL); + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_online_companions, NULL, NULL, + NULL); + + unlock_device_hotplug(); + + put_device(&device->dev); + return -EBUSY; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); acpi_bus_trim(device); + + unlock_device_hotplug(); + /* Device node has been unregistered. */ put_device(&device->dev); device = NULL; @@ -236,6 +318,7 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) int error; mutex_lock(&acpi_scan_lock); + lock_device_hotplug(); acpi_bus_get_device(handle, &device); if (device) { @@ -259,6 +342,7 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); out: + unlock_device_hotplug(); acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); mutex_unlock(&acpi_scan_lock); } diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index fcae5fa2e1b..5c5d1624fa2 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -780,6 +780,33 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name); } +static ssize_t force_remove_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", !!acpi_force_hot_remove); +} + +static ssize_t force_remove_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t size) +{ + bool val; + int ret; + + ret = strtobool(buf, &val); + if (ret < 0) + return ret; + + lock_device_hotplug(); + acpi_force_hot_remove = val; + unlock_device_hotplug(); + return size; +} + +static const struct kobj_attribute force_remove_attr = + __ATTR(force_remove, S_IRUGO | S_IWUSR, force_remove_show, + force_remove_store); + int __init acpi_sysfs_init(void) { int result; @@ -789,6 +816,10 @@ int __init acpi_sysfs_init(void) return result; hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj); + result = sysfs_create_file(hotplug_kobj, &force_remove_attr.attr); + if (result) + return result; + result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr); return result; } -- cgit v1.2.3-70-g09d2 From ac212b6980d8d5eda705864fc5a8ecddc6d6eacc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 3 May 2013 00:26:22 +0200 Subject: ACPI / processor: Use common hotplug infrastructure Split the ACPI processor driver into two parts, one that is non-modular, resides in the ACPI core and handles the enumeration and hotplug of processors and one that implements the rest of the existing processor driver functionality. The non-modular part uses an ACPI scan handler object to enumerate processors on the basis of information provided by the ACPI namespace and to hook up with the common ACPI hotplug infrastructure. It also populates the ACPI handle of each processor device having a corresponding object in the ACPI namespace, which allows the driver proper to bind to those devices, and makes the driver bind to them if it is readily available (i.e. loaded) when the scan handler's .attach() routine is running. There are a few reasons to make this change. First, switching the ACPI processor driver to using the common ACPI hotplug infrastructure reduces code duplication and size considerably, even though a new file is created along with a header comment etc. Second, since the common hotplug code attempts to offline devices before starting the (non-reversible) removal procedure, it will abort (and possibly roll back) hot-remove operations involving processors if cpu_down() returns an error code for one of them instead of continuing them blindly (if /sys/firmware/acpi/hotplug/force_remove is unset). That is a more desirable behavior than what the current code does. Finally, the separation of the scan/hotplug part from the driver proper makes it possible to simplify the driver's .remove() routine, because it doesn't need to worry about the possible cleanup related to processor removal any more (the scan/hotplug part is responsible for that now) and can handle device removal and driver removal symmetricaly (i.e. as appropriate). Some user-visible changes in sysfs are made (for example, the 'sysdev' link from the ACPI device node to the processor device's directory is gone and a 'physical_node' link is present instead and a corresponding 'firmware_node' is present in the processor device's directory, the processor driver is now visible under /sys/bus/cpu/drivers/ and bound to the processor device), but that shouldn't affect the functionality that users care about (frequency scaling, C-states and thermal management). Tested on my venerable Toshiba Portege R500. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Reviewed-by: Toshi Kani --- drivers/acpi/Makefile | 1 + drivers/acpi/acpi_processor.c | 484 ++++++++++++++++++++++++ drivers/acpi/glue.c | 6 +- drivers/acpi/internal.h | 3 + drivers/acpi/processor_driver.c | 807 ++++------------------------------------ drivers/acpi/scan.c | 1 + drivers/base/cpu.c | 11 + include/acpi/processor.h | 5 + 8 files changed, 587 insertions(+), 731 deletions(-) create mode 100644 drivers/acpi/acpi_processor.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index ecb743bf05a..93e49bde31b 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -34,6 +34,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o acpi-y += bus.o glue.o acpi-y += scan.o acpi-y += resource.o +acpi-y += acpi_processor.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c new file mode 100644 index 00000000000..587d2af4b32 --- /dev/null +++ b/drivers/acpi/acpi_processor.c @@ -0,0 +1,484 @@ +/* + * acpi_processor.c - ACPI processor enumeration support + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * Copyright (C) 2004 Dominik Brodowski + * Copyright (C) 2004 Anil S Keshavamurthy + * Copyright (C) 2013, Intel Corporation + * Rafael J. Wysocki + * + * 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 +#include +#include +#include +#include + +#include + +#include + +#include "internal.h" + +#define _COMPONENT ACPI_PROCESSOR_COMPONENT + +ACPI_MODULE_NAME("processor"); + +/* -------------------------------------------------------------------------- + Errata Handling + -------------------------------------------------------------------------- */ + +struct acpi_processor_errata errata __read_mostly; +EXPORT_SYMBOL_GPL(errata); + +static int acpi_processor_errata_piix4(struct pci_dev *dev) +{ + u8 value1 = 0; + u8 value2 = 0; + + + if (!dev) + return -EINVAL; + + /* + * Note that 'dev' references the PIIX4 ACPI Controller. + */ + + switch (dev->revision) { + case 0: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n")); + break; + case 1: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n")); + break; + case 2: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n")); + break; + case 3: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n")); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n")); + break; + } + + switch (dev->revision) { + + case 0: /* PIIX4 A-step */ + case 1: /* PIIX4 B-step */ + /* + * See specification changes #13 ("Manual Throttle Duty Cycle") + * and #14 ("Enabling and Disabling Manual Throttle"), plus + * erratum #5 ("STPCLK# Deassertion Time") from the January + * 2002 PIIX4 specification update. Applies to only older + * PIIX4 models. + */ + errata.piix4.throttle = 1; + + case 2: /* PIIX4E */ + case 3: /* PIIX4M */ + /* + * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA + * Livelock") from the January 2002 PIIX4 specification update. + * Applies to all PIIX4 models. + */ + + /* + * BM-IDE + * ------ + * Find the PIIX4 IDE Controller and get the Bus Master IDE + * Status register address. We'll use this later to read + * each IDE controller's DMA status to make sure we catch all + * DMA activity. + */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + errata.piix4.bmisx = pci_resource_start(dev, 4); + pci_dev_put(dev); + } + + /* + * Type-F DMA + * ---------- + * Find the PIIX4 ISA Controller and read the Motherboard + * DMA controller's status to see if Type-F (Fast) DMA mode + * is enabled (bit 7) on either channel. Note that we'll + * disable C3 support if this is enabled, as some legacy + * devices won't operate well if fast DMA is disabled. + */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, PCI_ANY_ID, NULL); + if (dev) { + pci_read_config_byte(dev, 0x76, &value1); + pci_read_config_byte(dev, 0x77, &value2); + if ((value1 & 0x80) || (value2 & 0x80)) + errata.piix4.fdma = 1; + pci_dev_put(dev); + } + + break; + } + + if (errata.piix4.bmisx) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Bus master activity detection (BM-IDE) erratum enabled\n")); + if (errata.piix4.fdma) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Type-F DMA livelock erratum (C3 disabled)\n")); + + return 0; +} + +static int acpi_processor_errata(struct acpi_processor *pr) +{ + int result = 0; + struct pci_dev *dev = NULL; + + + if (!pr) + return -EINVAL; + + /* + * PIIX4 + */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, + PCI_ANY_ID, NULL); + if (dev) { + result = acpi_processor_errata_piix4(dev); + pci_dev_put(dev); + } + + return result; +} + +/* -------------------------------------------------------------------------- + Initialization + -------------------------------------------------------------------------- */ + +#ifdef CONFIG_ACPI_HOTPLUG_CPU +static int acpi_processor_hotadd_init(struct acpi_processor *pr) +{ + unsigned long long sta; + acpi_status status; + int ret; + + status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) + return -ENODEV; + + ret = acpi_map_lsapic(pr->handle, &pr->id); + if (ret) + return ret; + + ret = arch_register_cpu(pr->id); + if (ret) { + acpi_unmap_lsapic(pr->id); + return ret; + } + + /* + * CPU got hot-added, but cpu_data is not initialized yet. Set a flag + * to delay cpu_idle/throttling initialization and do it when the CPU + * gets online for the first time. + */ + pr_info("CPU%d has been hot-added\n", pr->id); + pr->flags.need_hotplug_init = 1; + return 0; +} +#else +static inline int acpi_processor_hotadd_init(struct acpi_processor *pr) +{ + return -ENODEV; +} +#endif /* CONFIG_ACPI_HOTPLUG_CPU */ + +static int acpi_processor_get_info(struct acpi_device *device) +{ + union acpi_object object = { 0 }; + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + struct acpi_processor *pr = acpi_driver_data(device); + int cpu_index, device_declaration = 0; + acpi_status status = AE_OK; + static int cpu0_initialized; + + if (num_online_cpus() > 1) + errata.smp = TRUE; + + acpi_processor_errata(pr); + + /* + * Check to see if we have bus mastering arbitration control. This + * is required for proper C3 usage (to maintain cache coherency). + */ + if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) { + pr->flags.bm_control = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Bus mastering arbitration control present\n")); + } else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "No bus mastering arbitration control\n")); + + if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { + /* Declared with "Processor" statement; match ProcessorID */ + status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(&device->dev, + "Failed to evaluate processor object (0x%x)\n", + status); + return -ENODEV; + } + + /* + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. + * >>> 'acpi_get_processor_id(acpi_id, &id)' in + * arch/xxx/acpi.c + */ + pr->acpi_id = object.processor.proc_id; + } else { + /* + * Declared with "Device" statement; match _UID. + * Note that we don't handle string _UIDs yet. + */ + unsigned long long value; + status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, + NULL, &value); + if (ACPI_FAILURE(status)) { + dev_err(&device->dev, + "Failed to evaluate processor _UID (0x%x)\n", + status); + return -ENODEV; + } + device_declaration = 1; + pr->acpi_id = value; + } + cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); + + /* Handle UP system running SMP kernel, with no LAPIC in MADT */ + if (!cpu0_initialized && (cpu_index == -1) && + (num_online_cpus() == 1)) { + cpu_index = 0; + } + + cpu0_initialized = 1; + + pr->id = cpu_index; + + /* + * Extra Processor objects may be enumerated on MP systems with + * less than the max # of CPUs. They should be ignored _iff + * they are physically not present. + */ + if (pr->id == -1) { + int ret = acpi_processor_hotadd_init(pr); + if (ret) + return ret; + } + /* + * On some boxes several processors use the same processor bus id. + * But they are located in different scope. For example: + * \_SB.SCK0.CPU0 + * \_SB.SCK1.CPU0 + * Rename the processor device bus id. And the new bus id will be + * generated as the following format: + * CPU+CPU ID. + */ + sprintf(acpi_device_bid(device), "CPU%X", pr->id); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, + pr->acpi_id)); + + if (!object.processor.pblk_address) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); + else if (object.processor.pblk_length != 6) + dev_err(&device->dev, "Invalid PBLK length [%d]\n", + object.processor.pblk_length); + else { + pr->throttling.address = object.processor.pblk_address; + pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; + pr->throttling.duty_width = acpi_gbl_FADT.duty_width; + + pr->pblk = object.processor.pblk_address; + + /* + * We don't care about error returns - we just try to mark + * these reserved so that nobody else is confused into thinking + * that this region might be unused.. + * + * (In particular, allocating the IO range for Cardbus) + */ + request_region(pr->throttling.address, 6, "ACPI CPU throttle"); + } + + /* + * If ACPI describes a slot number for this CPU, we can use it to + * ensure we get the right value in the "physical id" field + * of /proc/cpuinfo + */ + status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); + if (ACPI_SUCCESS(status)) + arch_fix_phys_package_id(pr->id, object.integer.value); + + return 0; +} + +/* + * Do not put anything in here which needs the core to be online. + * For example MSR access or setting up things which check for cpuinfo_x86 + * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc. + * Such things have to be put in and set up by the processor driver's .probe(). + */ +static DEFINE_PER_CPU(void *, processor_device_array); + +static int __cpuinit acpi_processor_add(struct acpi_device *device, + const struct acpi_device_id *id) +{ + struct acpi_processor *pr; + struct device *dev; + int result = 0; + + pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); + if (!pr) + return -ENOMEM; + + if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { + result = -ENOMEM; + goto err_free_pr; + } + + pr->handle = device->handle; + strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); + device->driver_data = pr; + + result = acpi_processor_get_info(device); + if (result) /* Processor is not physically present or unavailable */ + return 0; + +#ifdef CONFIG_SMP + if (pr->id >= setup_max_cpus && pr->id != 0) + return 0; +#endif + + BUG_ON(pr->id >= nr_cpu_ids); + + /* + * Buggy BIOS check. + * ACPI id of processors can be reported wrongly by the BIOS. + * Don't trust it blindly + */ + if (per_cpu(processor_device_array, pr->id) != NULL && + per_cpu(processor_device_array, pr->id) != device) { + dev_warn(&device->dev, + "BIOS reported wrong ACPI id %d for the processor\n", + pr->id); + /* Give up, but do not abort the namespace scan. */ + goto err; + } + /* + * processor_device_array is not cleared on errors to allow buggy BIOS + * checks. + */ + per_cpu(processor_device_array, pr->id) = device; + + dev = get_cpu_device(pr->id); + ACPI_HANDLE_SET(dev, pr->handle); + result = acpi_bind_one(dev, NULL); + if (result) + goto err; + + pr->dev = dev; + dev->offline = pr->flags.need_hotplug_init; + + /* Trigger the processor driver's .probe() if present. */ + if (device_attach(dev) >= 0) + return 1; + + dev_err(dev, "Processor driver could not be attached\n"); + acpi_unbind_one(dev); + + err: + free_cpumask_var(pr->throttling.shared_cpu_map); + device->driver_data = NULL; + err_free_pr: + kfree(pr); + return result; +} + +#ifdef CONFIG_ACPI_HOTPLUG_CPU +/* -------------------------------------------------------------------------- + Removal + -------------------------------------------------------------------------- */ + +static void acpi_processor_remove(struct acpi_device *device) +{ + struct acpi_processor *pr; + + if (!device || !acpi_driver_data(device)) + return; + + pr = acpi_driver_data(device); + if (pr->id >= nr_cpu_ids) + goto out; + + /* + * The only reason why we ever get here is CPU hot-removal. The CPU is + * already offline and the ACPI device removal locking prevents it from + * being put back online at this point. + * + * Unbind the driver from the processor device and detach it from the + * ACPI companion object. + */ + device_release_driver(pr->dev); + acpi_unbind_one(pr->dev); + + /* Clean up. */ + per_cpu(processor_device_array, pr->id) = NULL; + try_offline_node(cpu_to_node(pr->id)); + + /* Remove the CPU. */ + get_online_cpus(); + arch_unregister_cpu(pr->id); + acpi_unmap_lsapic(pr->id); + put_online_cpus(); + + out: + free_cpumask_var(pr->throttling.shared_cpu_map); + kfree(pr); +} +#endif /* CONFIG_ACPI_HOTPLUG_CPU */ + +/* + * The following ACPI IDs are known to be suitable for representing as + * processor devices. + */ +static const struct acpi_device_id processor_device_ids[] = { + + { ACPI_PROCESSOR_OBJECT_HID, }, + { ACPI_PROCESSOR_DEVICE_HID, }, + + { } +}; + +static struct acpi_scan_handler __refdata processor_handler = { + .ids = processor_device_ids, + .attach = acpi_processor_add, +#ifdef CONFIG_ACPI_HOTPLUG_CPU + .detach = acpi_processor_remove, +#endif + .hotplug = { + .enabled = true, + }, +}; + +void __init acpi_processor_init(void) +{ + acpi_scan_add_handler_with_hotplug(&processor_handler, "processor"); +} diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 40a84cc6740..9783f400d85 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -105,7 +105,7 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address) } EXPORT_SYMBOL(acpi_get_child); -static int acpi_bind_one(struct device *dev, acpi_handle handle) +int acpi_bind_one(struct device *dev, acpi_handle handle) { struct acpi_device *acpi_dev; acpi_status status; @@ -188,8 +188,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) kfree(physical_node); goto err; } +EXPORT_SYMBOL_GPL(acpi_bind_one); -static int acpi_unbind_one(struct device *dev) +int acpi_unbind_one(struct device *dev) { struct acpi_device_physical_node *entry; struct acpi_device *acpi_dev; @@ -238,6 +239,7 @@ err: dev_err(dev, "Oops, 'acpi_handle' corrupt\n"); return -EINVAL; } +EXPORT_SYMBOL_GPL(acpi_unbind_one); static int acpi_platform_notify(struct device *dev) { diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 4548f0a114c..bf792595132 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -33,6 +33,7 @@ static inline void acpi_pci_slot_init(void) { } void acpi_pci_root_init(void); void acpi_pci_link_init(void); void acpi_pci_root_hp_init(void); +void acpi_processor_init(void); void acpi_platform_init(void); int acpi_sysfs_init(void); void acpi_csrt_init(void); @@ -79,6 +80,8 @@ 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_pnp_ids(struct acpi_device_pnp *pnp); +int acpi_bind_one(struct device *dev, acpi_handle handle); +int acpi_unbind_one(struct device *dev); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index c266cdc1178..ac28f18823b 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -1,11 +1,13 @@ /* - * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $) + * processor_driver.c - ACPI Processor Driver * * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh * Copyright (C) 2004 Dominik Brodowski * Copyright (C) 2004 Anil S Keshavamurthy * - Added processor hotplug support + * Copyright (C) 2013, Intel Corporation + * Rafael J. Wysocki * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -24,52 +26,29 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * TBD: - * 1. Make # power states dynamic. - * 2. Support duty_cycle values that span bit 4. - * 3. Optimize by having scheduler determine business instead of - * having us try to calculate it here. - * 4. Need C1 timing -- must modify kernel (IRQ handler) to get this. */ #include #include #include -#include -#include -#include #include #include -#include -#include #include #include #include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include + #include +#include "internal.h" + #define PREFIX "ACPI: " -#define ACPI_PROCESSOR_CLASS "processor" -#define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" #define ACPI_PROCESSOR_FILE_THROTTLING "throttling" #define ACPI_PROCESSOR_FILE_LIMIT "limit" #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 -#define ACPI_PROCESSOR_DEVICE_HID "ACPI0007" #define ACPI_PROCESSOR_LIMIT_USER 0 #define ACPI_PROCESSOR_LIMIT_THERMAL 1 @@ -81,12 +60,8 @@ MODULE_AUTHOR("Paul Diefenbaugh"); 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); -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); -static int acpi_processor_start(struct acpi_processor *pr); +static int acpi_processor_start(struct device *dev); +static int acpi_processor_stop(struct device *dev); static const struct acpi_device_id processor_device_ids[] = { {ACPI_PROCESSOR_OBJECT_HID, 0}, @@ -95,295 +70,27 @@ static const struct acpi_device_id processor_device_ids[] = { }; MODULE_DEVICE_TABLE(acpi, processor_device_ids); -static struct acpi_driver acpi_processor_driver = { +static struct device_driver acpi_processor_driver = { .name = "processor", - .class = ACPI_PROCESSOR_CLASS, - .ids = processor_device_ids, - .ops = { - .add = acpi_processor_add, - .remove = acpi_processor_remove, - .notify = acpi_processor_notify, - }, + .bus = &cpu_subsys, + .acpi_match_table = processor_device_ids, + .probe = acpi_processor_start, + .remove = acpi_processor_stop, }; -#define INSTALL_NOTIFY_HANDLER 1 -#define UNINSTALL_NOTIFY_HANDLER 2 - DEFINE_PER_CPU(struct acpi_processor *, processors); EXPORT_PER_CPU_SYMBOL(processors); -struct acpi_processor_errata errata __read_mostly; - -/* -------------------------------------------------------------------------- - Errata Handling - -------------------------------------------------------------------------- */ - -static int acpi_processor_errata_piix4(struct pci_dev *dev) +static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) { - u8 value1 = 0; - u8 value2 = 0; - - - if (!dev) - return -EINVAL; - - /* - * Note that 'dev' references the PIIX4 ACPI Controller. - */ - - switch (dev->revision) { - case 0: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n")); - break; - case 1: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n")); - break; - case 2: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n")); - break; - case 3: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n")); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n")); - break; - } - - switch (dev->revision) { - - case 0: /* PIIX4 A-step */ - case 1: /* PIIX4 B-step */ - /* - * See specification changes #13 ("Manual Throttle Duty Cycle") - * and #14 ("Enabling and Disabling Manual Throttle"), plus - * erratum #5 ("STPCLK# Deassertion Time") from the January - * 2002 PIIX4 specification update. Applies to only older - * PIIX4 models. - */ - errata.piix4.throttle = 1; - - case 2: /* PIIX4E */ - case 3: /* PIIX4M */ - /* - * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA - * Livelock") from the January 2002 PIIX4 specification update. - * Applies to all PIIX4 models. - */ - - /* - * BM-IDE - * ------ - * Find the PIIX4 IDE Controller and get the Bus Master IDE - * Status register address. We'll use this later to read - * each IDE controller's DMA status to make sure we catch all - * DMA activity. - */ - dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB, - PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - errata.piix4.bmisx = pci_resource_start(dev, 4); - pci_dev_put(dev); - } - - /* - * Type-F DMA - * ---------- - * Find the PIIX4 ISA Controller and read the Motherboard - * DMA controller's status to see if Type-F (Fast) DMA mode - * is enabled (bit 7) on either channel. Note that we'll - * disable C3 support if this is enabled, as some legacy - * devices won't operate well if fast DMA is disabled. - */ - dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_0, - PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - pci_read_config_byte(dev, 0x76, &value1); - pci_read_config_byte(dev, 0x77, &value2); - if ((value1 & 0x80) || (value2 & 0x80)) - errata.piix4.fdma = 1; - pci_dev_put(dev); - } - - break; - } - - if (errata.piix4.bmisx) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus master activity detection (BM-IDE) erratum enabled\n")); - if (errata.piix4.fdma) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type-F DMA livelock erratum (C3 disabled)\n")); - - return 0; -} - -static int acpi_processor_errata(struct acpi_processor *pr) -{ - int result = 0; - struct pci_dev *dev = NULL; - - - if (!pr) - return -EINVAL; - - /* - * PIIX4 - */ - dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, - PCI_ANY_ID, NULL); - if (dev) { - result = acpi_processor_errata_piix4(dev); - pci_dev_put(dev); - } - - return result; -} - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ - -static int acpi_processor_get_info(struct acpi_device *device) -{ - acpi_status status = 0; - union acpi_object object = { 0 }; - struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + struct acpi_device *device = data; struct acpi_processor *pr; - int cpu_index, device_declaration = 0; - static int cpu0_initialized; - - pr = acpi_driver_data(device); - if (!pr) - return -EINVAL; - - if (num_online_cpus() > 1) - errata.smp = TRUE; - - acpi_processor_errata(pr); - - /* - * Check to see if we have bus mastering arbitration control. This - * is required for proper C3 usage (to maintain cache coherency). - */ - if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) { - pr->flags.bm_control = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Bus mastering arbitration control present\n")); - } else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No bus mastering arbitration control\n")); - - if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { - /* Declared with "Processor" statement; match ProcessorID */ - status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) { - dev_err(&device->dev, - "Failed to evaluate processor object (0x%x)\n", - status); - return -ENODEV; - } - - /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in - * arch/xxx/acpi.c - */ - pr->acpi_id = object.processor.proc_id; - } else { - /* - * Declared with "Device" statement; match _UID. - * Note that we don't handle string _UIDs yet. - */ - unsigned long long value; - status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, - NULL, &value); - if (ACPI_FAILURE(status)) { - dev_err(&device->dev, - "Failed to evaluate processor _UID (0x%x)\n", - status); - return -ENODEV; - } - device_declaration = 1; - pr->acpi_id = value; - } - cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); - - /* Handle UP system running SMP kernel, with no LAPIC in MADT */ - if (!cpu0_initialized && (cpu_index == -1) && - (num_online_cpus() == 1)) { - cpu_index = 0; - } - - cpu0_initialized = 1; - - pr->id = cpu_index; - - /* - * Extra Processor objects may be enumerated on MP systems with - * less than the max # of CPUs. They should be ignored _iff - * they are physically not present. - */ - if (pr->id == -1) { - if (ACPI_FAILURE(acpi_processor_hotadd_init(pr))) - return -ENODEV; - } - /* - * On some boxes several processors use the same processor bus id. - * But they are located in different scope. For example: - * \_SB.SCK0.CPU0 - * \_SB.SCK1.CPU0 - * Rename the processor device bus id. And the new bus id will be - * generated as the following format: - * CPU+CPU ID. - */ - sprintf(acpi_device_bid(device), "CPU%X", pr->id); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, - pr->acpi_id)); - - if (!object.processor.pblk_address) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); - else if (object.processor.pblk_length != 6) - dev_err(&device->dev, "Invalid PBLK length [%d]\n", - object.processor.pblk_length); - else { - pr->throttling.address = object.processor.pblk_address; - pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; - pr->throttling.duty_width = acpi_gbl_FADT.duty_width; - - pr->pblk = object.processor.pblk_address; - - /* - * We don't care about error returns - we just try to mark - * these reserved so that nobody else is confused into thinking - * that this region might be unused.. - * - * (In particular, allocating the IO range for Cardbus) - */ - request_region(pr->throttling.address, 6, "ACPI CPU throttle"); - } - - /* - * If ACPI describes a slot number for this CPU, we can use it - * ensure we get the right value in the "physical id" field - * of /proc/cpuinfo - */ - status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); - if (ACPI_SUCCESS(status)) - arch_fix_phys_package_id(pr->id, object.integer.value); - - return 0; -} - -static DEFINE_PER_CPU(void *, processor_device_array); - -static void acpi_processor_notify(struct acpi_device *device, u32 event) -{ - struct acpi_processor *pr = acpi_driver_data(device); int saved; + if (device->handle != handle) + return; + + pr = acpi_driver_data(device); if (!pr) return; @@ -420,55 +127,62 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) return; } -static int acpi_cpu_soft_notify(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static __cpuinit int __acpi_processor_start(struct acpi_device *device); + +static int __cpuinit acpi_cpu_soft_notify(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; struct acpi_processor *pr = per_cpu(processors, cpu); + struct acpi_device *device; - if (action == CPU_ONLINE && pr) { - /* CPU got physically hotplugged and onlined the first time: - * Initialize missing things + if (!pr || acpi_bus_get_device(pr->handle, &device)) + return NOTIFY_DONE; + + if (action == CPU_ONLINE) { + /* + * CPU got physically hotplugged and onlined for the first time: + * Initialize missing things. */ if (pr->flags.need_hotplug_init) { + int ret; + 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; - /* Normal CPU soft online event */ + ret = __acpi_processor_start(device); + WARN(ret, "Failed to start CPU: %d\n", pr->id); } else { + /* Normal CPU soft online event. */ acpi_processor_ppc_has_changed(pr, 0); acpi_processor_hotplug(pr); acpi_processor_reevaluate_tstate(pr, action); acpi_processor_tstate_has_changed(pr); } - } - if (action == CPU_DEAD && pr) { - /* invalidate the flag.throttling after one CPU is offline */ + } else if (action == CPU_DEAD) { + /* Invalidate flag.throttling after the CPU is offline. */ acpi_processor_reevaluate_tstate(pr, action); } return NOTIFY_OK; } -static struct notifier_block acpi_cpu_notifier = +static struct notifier_block __refdata acpi_cpu_notifier = { .notifier_call = acpi_cpu_soft_notify, }; -/* - * acpi_processor_start() is called by the cpu_hotplug_notifier func: - * acpi_cpu_soft_notify(). Getting it __cpuinit{data} is difficult, the - * root cause seem to be that acpi_processor_uninstall_hotplug_notify() - * is in the module_exit (__exit) func. Allowing acpi_processor_start() - * to not be in __cpuinit section, but being called from __cpuinit funcs - * via __ref looks like the right thing to do here. - */ -static __ref int acpi_processor_start(struct acpi_processor *pr) +static __cpuinit int __acpi_processor_start(struct acpi_device *device) { - struct acpi_device *device = per_cpu(processor_device_array, pr->id); + struct acpi_processor *pr = acpi_driver_data(device); + acpi_status status; int result = 0; + if (!pr) + return -ENODEV; + + if (pr->flags.need_hotplug_init) + return 0; + #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); acpi_processor_load_module(pr); @@ -506,129 +220,48 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) goto err_remove_sysfs_thermal; } - return 0; + status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_processor_notify, device); + if (ACPI_SUCCESS(status)) + return 0; -err_remove_sysfs_thermal: + sysfs_remove_link(&pr->cdev->device.kobj, "device"); + err_remove_sysfs_thermal: sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); -err_thermal_unregister: + err_thermal_unregister: thermal_cooling_device_unregister(pr->cdev); -err_power_exit: + err_power_exit: acpi_processor_power_exit(pr); - return result; } -/* - * Do not put anything in here which needs the core to be online. - * For example MSR access or setting up things which check for cpuinfo_x86 - * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc. - * Such things have to be put in and set up above in acpi_processor_start() - */ -static int __cpuinit acpi_processor_add(struct acpi_device *device) +static int __cpuinit acpi_processor_start(struct device *dev) { - struct acpi_processor *pr = NULL; - int result = 0; - struct device *dev; - - pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); - if (!pr) - return -ENOMEM; + struct acpi_device *device; - if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { - result = -ENOMEM; - goto err_free_pr; - } - - pr->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); - device->driver_data = pr; - - result = acpi_processor_get_info(device); - if (result) { - /* Processor is physically not present */ - return 0; - } - -#ifdef CONFIG_SMP - if (pr->id >= setup_max_cpus && pr->id != 0) - return 0; -#endif - - BUG_ON(pr->id >= nr_cpu_ids); - - /* - * Buggy BIOS check - * ACPI id of processors can be reported wrongly by the BIOS. - * Don't trust it blindly - */ - if (per_cpu(processor_device_array, pr->id) != NULL && - per_cpu(processor_device_array, pr->id) != device) { - dev_warn(&device->dev, - "BIOS reported wrong ACPI id %d for the processor\n", - pr->id); - result = -ENODEV; - goto err_free_cpumask; - } - per_cpu(processor_device_array, pr->id) = device; - - per_cpu(processors, pr->id) = pr; + if (acpi_bus_get_device(ACPI_HANDLE(dev), &device)) + return -ENODEV; - dev = get_cpu_device(pr->id); - if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) { - result = -EFAULT; - goto err_clear_processor; - } - - /* - * Do not start hotplugged CPUs now, but when they - * are onlined the first time - */ - if (pr->flags.need_hotplug_init) - return 0; - - result = acpi_processor_start(pr); - if (result) - goto err_remove_sysfs; - - return 0; - -err_remove_sysfs: - sysfs_remove_link(&device->dev.kobj, "sysdev"); -err_clear_processor: - /* - * processor_device_array is not cleared to allow checks for buggy BIOS - */ - per_cpu(processors, pr->id) = NULL; -err_free_cpumask: - free_cpumask_var(pr->throttling.shared_cpu_map); -err_free_pr: - kfree(pr); - return result; + return __acpi_processor_start(device); } -static int acpi_processor_remove(struct acpi_device *device) +static int acpi_processor_stop(struct device *dev) { - struct acpi_processor *pr = NULL; + struct acpi_device *device; + struct acpi_processor *pr; + if (acpi_bus_get_device(ACPI_HANDLE(dev), &device)) + return 0; - if (!device || !acpi_driver_data(device)) - return -EINVAL; + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_processor_notify); pr = acpi_driver_data(device); - - if (pr->id >= nr_cpu_ids) - goto free; - - if (device->removal_type == ACPI_BUS_REMOVAL_EJECT) { - if (acpi_processor_handle_eject(pr)) - return -EINVAL; - } + if (!pr) + return 0; acpi_processor_power_exit(pr); - sysfs_remove_link(&device->dev.kobj, "sysdev"); - if (pr->cdev) { sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); sysfs_remove_link(&pr->cdev->device.kobj, "device"); @@ -637,331 +270,47 @@ static int acpi_processor_remove(struct acpi_device *device) } 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); - kfree(pr); - return 0; } -#ifdef CONFIG_ACPI_HOTPLUG_CPU -/**************************************************************************** - * Acpi processor hotplug support * - ****************************************************************************/ - -static int is_processor_present(acpi_handle handle) -{ - acpi_status status; - unsigned long long sta = 0; - - - status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - - if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) - return 1; - - /* - * _STA is mandatory for a processor that supports hot plug - */ - if (status == AE_NOT_FOUND) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Processor does not support hot plug\n")); - else - ACPI_EXCEPTION((AE_INFO, status, - "Processor Device is not present")); - return 0; -} - -static void acpi_processor_hotplug_notify(acpi_handle handle, - u32 event, void *data) -{ - 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: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Processor driver received %s event\n", - (event == ACPI_NOTIFY_BUS_CHECK) ? - "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK")); - - if (!is_processor_present(handle)) - break; - - if (!acpi_bus_get_device(handle, &device)) - break; - - result = acpi_bus_scan(handle); - if (result) { - 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; - - case ACPI_NOTIFY_EJECT_REQUEST: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "received ACPI_NOTIFY_EJECT_REQUEST\n")); - - if (acpi_bus_get_device(handle, &device)) { - acpi_handle_err(handle, - "Device don't exist, dropping EJECT\n"); - break; - } - if (!acpi_driver_data(device)) { - acpi_handle_err(handle, - "Driver data is NULL, dropping EJECT\n"); - 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 */ - goto out; - } - - /* Inform firmware that the hotplug operation has completed */ - (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL); - - out: - acpi_scan_lock_release(); -} - -static acpi_status is_processor_device(acpi_handle handle) -{ - struct acpi_device_info *info; - char *hid; - acpi_status status; - - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) - return status; - - if (info->type == ACPI_TYPE_PROCESSOR) { - kfree(info); - return AE_OK; /* found a processor object */ - } - - if (!(info->valid & ACPI_VALID_HID)) { - kfree(info); - return AE_ERROR; - } - - hid = info->hardware_id.string; - if ((hid == NULL) || strcmp(hid, ACPI_PROCESSOR_DEVICE_HID)) { - kfree(info); - return AE_ERROR; - } - - kfree(info); - return AE_OK; /* found a processor device object */ -} - -static acpi_status -processor_walk_namespace_cb(acpi_handle handle, - u32 lvl, void *context, void **rv) -{ - acpi_status status; - int *action = context; - - status = is_processor_device(handle); - if (ACPI_FAILURE(status)) - return AE_OK; /* not a processor; continue to walk */ - - switch (*action) { - case INSTALL_NOTIFY_HANDLER: - acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - acpi_processor_hotplug_notify, - NULL); - break; - case UNINSTALL_NOTIFY_HANDLER: - acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - acpi_processor_hotplug_notify); - break; - default: - break; - } - - /* found a processor; skip walking underneath */ - return AE_CTRL_DEPTH; -} - -static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr) -{ - acpi_handle handle = pr->handle; - - if (!is_processor_present(handle)) { - return AE_ERROR; - } - - if (acpi_map_lsapic(handle, &pr->id)) - return AE_ERROR; - - if (arch_register_cpu(pr->id)) { - acpi_unmap_lsapic(pr->id); - return AE_ERROR; - } - - /* CPU got hot-plugged, but cpu_data is not initialized yet - * Set flag to delay cpu_idle/throttling initialization - * in: - * acpi_processor_add() - * acpi_processor_get_info() - * and do it when the CPU gets online the first time - * TBD: Cleanup above functions and try to do this more elegant. - */ - pr_info("CPU %d got hotplugged\n", pr->id); - pr->flags.need_hotplug_init = 1; - - return AE_OK; -} - -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 -static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr) -{ - return AE_ERROR; -} -static int acpi_processor_handle_eject(struct acpi_processor *pr) -{ - return (-EINVAL); -} -#endif - -static -void acpi_processor_install_hotplug_notify(void) -{ -#ifdef CONFIG_ACPI_HOTPLUG_CPU - int action = INSTALL_NOTIFY_HANDLER; - acpi_walk_namespace(ACPI_TYPE_ANY, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - processor_walk_namespace_cb, NULL, &action, NULL); -#endif - register_hotcpu_notifier(&acpi_cpu_notifier); -} - -static -void acpi_processor_uninstall_hotplug_notify(void) -{ -#ifdef CONFIG_ACPI_HOTPLUG_CPU - int action = UNINSTALL_NOTIFY_HANDLER; - acpi_walk_namespace(ACPI_TYPE_ANY, - ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - processor_walk_namespace_cb, NULL, &action, NULL); -#endif - unregister_hotcpu_notifier(&acpi_cpu_notifier); -} - /* * We keep the driver loaded even when ACPI is not running. * This is needed for the powernow-k8 driver, that works even without * ACPI, but needs symbols from this driver */ -static int __init acpi_processor_init(void) +static int __init acpi_processor_driver_init(void) { int result = 0; if (acpi_disabled) return 0; - result = acpi_bus_register_driver(&acpi_processor_driver); + result = driver_register(&acpi_processor_driver); if (result < 0) return result; acpi_processor_syscore_init(); - - acpi_processor_install_hotplug_notify(); - + register_hotcpu_notifier(&acpi_cpu_notifier); acpi_thermal_cpufreq_init(); - acpi_processor_ppc_init(); - acpi_processor_throttling_init(); - return 0; } -static void __exit acpi_processor_exit(void) +static void __exit acpi_processor_driver_exit(void) { if (acpi_disabled) return; acpi_processor_ppc_exit(); - acpi_thermal_cpufreq_exit(); - - acpi_processor_uninstall_hotplug_notify(); - + unregister_hotcpu_notifier(&acpi_cpu_notifier); acpi_processor_syscore_exit(); - - acpi_bus_unregister_driver(&acpi_processor_driver); - - return; + driver_unregister(&acpi_processor_driver); } -module_init(acpi_processor_init); -module_exit(acpi_processor_exit); +module_init(acpi_processor_driver_init); +module_exit(acpi_processor_driver_exit); MODULE_ALIAS("processor"); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4fd392005ef..ad82bb2a37e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2124,6 +2124,7 @@ int __init acpi_scan_init(void) acpi_pci_root_init(); acpi_pci_link_init(); + acpi_processor_init(); acpi_platform_init(); acpi_lpss_init(); acpi_csrt_init(); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 25c8768172e..7431ba6fc2d 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -13,11 +13,21 @@ #include #include #include +#include #include "base.h" static DEFINE_PER_CPU(struct device *, cpu_sys_devices); +static int cpu_subsys_match(struct device *dev, struct device_driver *drv) +{ + /* ACPI style match is the only one that may succeed. */ + if (acpi_driver_match_device(dev, drv)) + return 1; + + return 0; +} + #ifdef CONFIG_HOTPLUG_CPU static void change_cpu_under_node(struct cpu *cpu, unsigned int from_nid, unsigned int to_nid) @@ -98,6 +108,7 @@ static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); struct bus_type cpu_subsys = { .name = "cpu", .dev_name = "cpu", + .match = cpu_subsys_match, #ifdef CONFIG_HOTPLUG_CPU .online = cpu_subsys_online, .offline = cpu_subsys_offline, diff --git a/include/acpi/processor.h b/include/acpi/processor.h index ea69367fdd3..66096d06925 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -6,6 +6,10 @@ #include #include +#define ACPI_PROCESSOR_CLASS "processor" +#define ACPI_PROCESSOR_DEVICE_NAME "Processor" +#define ACPI_PROCESSOR_DEVICE_HID "ACPI0007" + #define ACPI_PROCESSOR_BUSY_METRIC 10 #define ACPI_PROCESSOR_MAX_POWER 8 @@ -207,6 +211,7 @@ struct acpi_processor { struct acpi_processor_throttling throttling; struct acpi_processor_limit limit; struct thermal_cooling_device *cdev; + struct device *dev; /* Processor device. */ }; struct acpi_processor_errata { -- cgit v1.2.3-70-g09d2 From e2ff39400d81233374e780b133496a2296643d7d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 8 May 2013 00:29:49 +0200 Subject: ACPI / memhotplug: Bind removable memory blocks to ACPI device nodes During ACPI memory hotplug configuration bind memory blocks residing in modules removable through the standard ACPI mechanism to struct acpi_device objects associated with ACPI namespace objects representing those modules. Accordingly, unbind those memory blocks from the struct acpi_device objects when the memory modules in question are being removed. When "offline" operation for devices representing memory blocks is introduced, this will allow the ACPI core's device hot-remove code to use it to carry out remove_memory() for those memory blocks and check the results of that before it actually removes the modules holding them from the system. Since walk_memory_range() is used for accessing all memory blocks corresponding to a given ACPI namespace object, it is exported from memory_hotplug.c so that the code in acpi_memhotplug.c can use it. Signed-off-by: Rafael J. Wysocki Tested-by: Vasilis Liaskovitis Reviewed-by: Toshi Kani --- drivers/acpi/acpi_memhotplug.c | 53 +++++++++++++++++++++++++++++++++++++++--- include/linux/memory_hotplug.h | 2 ++ mm/memory_hotplug.c | 4 +++- 3 files changed, 55 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5e6301e9492..5590db12028 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -28,6 +28,7 @@ */ #include +#include #include #include "internal.h" @@ -166,13 +167,50 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device) return 0; } +static unsigned long acpi_meminfo_start_pfn(struct acpi_memory_info *info) +{ + return PFN_DOWN(info->start_addr); +} + +static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info) +{ + return PFN_UP(info->start_addr + info->length-1); +} + +static int acpi_bind_memblk(struct memory_block *mem, void *arg) +{ + return acpi_bind_one(&mem->dev, (acpi_handle)arg); +} + +static int acpi_bind_memory_blocks(struct acpi_memory_info *info, + acpi_handle handle) +{ + return walk_memory_range(acpi_meminfo_start_pfn(info), + acpi_meminfo_end_pfn(info), (void *)handle, + acpi_bind_memblk); +} + +static int acpi_unbind_memblk(struct memory_block *mem, void *arg) +{ + acpi_unbind_one(&mem->dev); + return 0; +} + +static void acpi_unbind_memory_blocks(struct acpi_memory_info *info, + acpi_handle handle) +{ + walk_memory_range(acpi_meminfo_start_pfn(info), + acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk); +} + static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) { + acpi_handle handle = mem_device->device->handle; int result, num_enabled = 0; struct acpi_memory_info *info; int node; - node = acpi_get_node(mem_device->device->handle); + node = acpi_get_node(handle); /* * Tell the VM there is more memory here... * Note: Assume that this function returns zero on success @@ -203,6 +241,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) if (result && result != -EEXIST) continue; + result = acpi_bind_memory_blocks(info, handle); + if (result) { + acpi_unbind_memory_blocks(info, handle); + return -ENODEV; + } + info->enabled = 1; /* @@ -229,10 +273,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) { + acpi_handle handle = mem_device->device->handle; int result = 0, nid; struct acpi_memory_info *info, *n; - nid = acpi_get_node(mem_device->device->handle); + nid = acpi_get_node(handle); list_for_each_entry_safe(info, n, &mem_device->res_list, list) { if (!info->enabled) @@ -240,6 +285,8 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) if (nid < 0) nid = memory_add_physaddr_to_nid(info->start_addr); + + acpi_unbind_memory_blocks(info, handle); result = remove_memory(nid, info->start_addr, info->length); if (result) return result; @@ -300,7 +347,7 @@ static int acpi_memory_device_add(struct acpi_device *device, if (result) { dev_err(&device->dev, "acpi_memory_enable_device() error\n"); acpi_memory_device_free(mem_device); - return -ENODEV; + return result; } dev_dbg(&device->dev, "Memory device configured by ACPI\n"); diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 3e622c61092..2975b7b2a9d 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -245,6 +245,8 @@ static inline int is_mem_section_removable(unsigned long pfn, static inline void try_offline_node(int nid) {} #endif /* CONFIG_MEMORY_HOTREMOVE */ +extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, + void *arg, int (*func)(struct memory_block *, void *)); extern int mem_online_node(int nid); extern int add_memory(int nid, u64 start, u64 size); extern int arch_add_memory(int nid, u64 start, u64 size); diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a221fac1f47..5ea1287ee91 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1618,6 +1618,7 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages) { return __offline_pages(start_pfn, start_pfn + nr_pages, 120 * HZ); } +#endif /* CONFIG_MEMORY_HOTREMOVE */ /** * walk_memory_range - walks through all mem sections in [start_pfn, end_pfn) @@ -1631,7 +1632,7 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages) * * Returns the return value of func. */ -static int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, +int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, void *arg, int (*func)(struct memory_block *, void *)) { struct memory_block *mem = NULL; @@ -1668,6 +1669,7 @@ static int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, return 0; } +#ifdef CONFIG_MEMORY_HOTREMOVE /** * offline_memory_block_cb - callback function for offlining memory block * @mem: the memory block to be offlined -- cgit v1.2.3-70-g09d2 From 2e4f1db49d97222110b6add9a2c6cf5251a41e35 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 30 May 2013 21:55:46 +0200 Subject: ACPI / processor: Initialize per_cpu(processors, pr->id) properly Commit ac212b6 (ACPI / processor: Use common hotplug infrastructure) forgot about initializing the per-CPU 'processors' variables which lead to ACPI cpuidle failure to use C-states and caused boot slowdown on multi-CPU machines. Fix the problem by adding per_cpu(processors, pr->id) initialization to acpi_processor_add() and add make acpi_processor_remove() clean it up as appropriate. Also modify acpi_processor_stop() so that it doesn't clear per_cpu(processors, pr->id) on processor driver removal which would then cause problems to happen when the driver is loaded again. This version of the patch contains fixes from Yinghai Lu. Reported-and-tested-by: Yinghai Lu Reported-and-tested-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 6 ++++++ drivers/acpi/processor_driver.c | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 587d2af4b32..cae2641e8d8 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -29,6 +29,9 @@ ACPI_MODULE_NAME("processor"); +DEFINE_PER_CPU(struct acpi_processor *, processors); +EXPORT_PER_CPU_SYMBOL(processors); + /* -------------------------------------------------------------------------- Errata Handling -------------------------------------------------------------------------- */ @@ -387,6 +390,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device, * checks. */ per_cpu(processor_device_array, pr->id) = device; + per_cpu(processors, pr->id) = pr; dev = get_cpu_device(pr->id); ACPI_HANDLE_SET(dev, pr->handle); @@ -407,6 +411,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device, err: free_cpumask_var(pr->throttling.shared_cpu_map); device->driver_data = NULL; + per_cpu(processors, pr->id) = NULL; err_free_pr: kfree(pr); return result; @@ -441,6 +446,7 @@ static void acpi_processor_remove(struct acpi_device *device) /* Clean up. */ per_cpu(processor_device_array, pr->id) = NULL; + per_cpu(processors, pr->id) = NULL; try_offline_node(cpu_to_node(pr->id)); /* Remove the CPU. */ diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index ac28f18823b..d93963f1e8f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -78,9 +78,6 @@ static struct device_driver acpi_processor_driver = { .remove = acpi_processor_stop, }; -DEFINE_PER_CPU(struct acpi_processor *, processors); -EXPORT_PER_CPU_SYMBOL(processors); - static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) { struct acpi_device *device = data; @@ -268,8 +265,6 @@ static int acpi_processor_stop(struct device *dev) thermal_cooling_device_unregister(pr->cdev); pr->cdev = NULL; } - - per_cpu(processors, pr->id) = NULL; return 0; } -- cgit v1.2.3-70-g09d2 From 2e199192df85eb936a7829dc28b57b85c59c86fc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 May 2013 10:40:35 +0200 Subject: ACPI: Drop removal_type field from struct acpi_device The ACPI processor driver was the only user of the removal_type field in struct acpi_device, but it doesn't use that field any more after recent changes. Thus, removal_type has no more users, so drop it along with the associated data type. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 2 -- include/acpi/acpi_bus.h | 8 -------- 2 files changed, 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ad82bb2a37e..ba8ee6cbf0f 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1036,7 +1036,6 @@ int acpi_device_add(struct acpi_device *device, printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", dev_name(&device->dev)); - device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; err: @@ -2025,7 +2024,6 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, 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); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 4d5d3e7ba33..1a681ee2aa0 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -63,13 +63,6 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; -enum acpi_bus_removal_type { - ACPI_BUS_REMOVAL_NORMAL = 0, - ACPI_BUS_REMOVAL_EJECT, - ACPI_BUS_REMOVAL_SUPRISE, - ACPI_BUS_REMOVAL_TYPE_COUNT -}; - enum acpi_bus_device_type { ACPI_BUS_TYPE_DEVICE = 0, ACPI_BUS_TYPE_POWER, @@ -311,7 +304,6 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct device dev; - enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; struct mutex physical_node_lock; -- cgit v1.2.3-70-g09d2 From be547436c22c3b7d934d9afd841cfd7a6807f7ab Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 May 2013 10:40:56 +0200 Subject: ACPI / processor: Pass processor object handle to acpi_bind_one() Make acpi_processor_add() pass the ACPI handle of the processor namespace object to acpi_bind_one() instead of setting it directly to allow acpi_bind_one() to catch possible bugs causing the ACPI handle of the processor device to be set earlier. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/acpi_processor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index cae2641e8d8..157e7389a5f 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -393,8 +393,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device, per_cpu(processors, pr->id) = pr; dev = get_cpu_device(pr->id); - ACPI_HANDLE_SET(dev, pr->handle); - result = acpi_bind_one(dev, NULL); + result = acpi_bind_one(dev, pr->handle); if (result) goto err; -- cgit v1.2.3-70-g09d2 From 303bfdb1a14d0460feb859cd008ff81da36b517c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 23 May 2013 10:43:13 +0200 Subject: ACPI / scan: Add second pass of companion offlining to hot-remove code As indicated by comments in mm/memory_hotplug.c:remove_memory(), if CONFIG_MEMCG is set, it may not be possible to offline all of the memory blocks held by one module (FRU) in one pass (because one of them may be used by the others to store page cgroup in that case and that block has to be offlined before the other ones). To handle that arguably corner case, add a second pass of companion device offlining to acpi_scan_hot_remove() and make it ignore errors returned in the first pass (and make it skip the second pass if the first one is successful). Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani --- drivers/acpi/scan.c | 71 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 19 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ba8ee6cbf0f..2959fe1ce43 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -131,6 +131,7 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; + bool second_pass = (bool)data; acpi_status status = AE_OK; if (acpi_bus_get_device(handle, &device)) @@ -141,15 +142,26 @@ static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, list_for_each_entry(pn, &device->physical_node_list, node) { int ret; + if (second_pass) { + /* Skip devices offlined by the first pass. */ + if (pn->put_online) + continue; + } else { + pn->put_online = false; + } ret = device_offline(pn->dev); if (acpi_force_hot_remove) continue; - if (ret < 0) { - status = AE_ERROR; - break; + if (ret >= 0) { + pn->put_online = !ret; + } else { + *ret_p = pn->dev; + if (second_pass) { + status = AE_ERROR; + break; + } } - pn->put_online = !ret; } mutex_unlock(&device->physical_node_lock); @@ -185,6 +197,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device) acpi_handle not_used; struct acpi_object_list arg_list; union acpi_object arg; + struct device *errdev; acpi_status status; unsigned long long sta; @@ -197,22 +210,42 @@ static int acpi_scan_hot_remove(struct acpi_device *device) lock_device_hotplug(); - status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, NULL, - NULL); - if (ACPI_SUCCESS(status) || acpi_force_hot_remove) - status = acpi_bus_offline_companions(handle, 0, NULL, NULL); - - if (ACPI_FAILURE(status) && !acpi_force_hot_remove) { - acpi_bus_online_companions(handle, 0, NULL, NULL); + /* + * Carry out two passes here and ignore errors in the first pass, + * because if the devices in question are memory blocks and + * CONFIG_MEMCG is set, one of the blocks may hold data structures + * that the other blocks depend on, but it is not known in advance which + * block holds them. + * + * If the first pass is successful, the second one isn't needed, though. + */ + errdev = NULL; + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + NULL, acpi_bus_offline_companions, + (void *)false, (void **)&errdev); + acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev); + if (errdev) { + errdev = NULL; acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_online_companions, NULL, NULL, - NULL); - - unlock_device_hotplug(); - - put_device(&device->dev); - return -EBUSY; + NULL, acpi_bus_offline_companions, + (void *)true , (void **)&errdev); + if (!errdev || acpi_force_hot_remove) + acpi_bus_offline_companions(handle, 0, (void *)true, + (void **)&errdev); + + if (errdev && !acpi_force_hot_remove) { + dev_warn(errdev, "Offline failed.\n"); + acpi_bus_online_companions(handle, 0, NULL, NULL); + acpi_walk_namespace(ACPI_TYPE_ANY, handle, + ACPI_UINT32_MAX, + acpi_bus_online_companions, NULL, + NULL, NULL); + + unlock_device_hotplug(); + + put_device(&device->dev); + return -EBUSY; + } } ACPI_DEBUG_PRINT((ACPI_DB_INFO, -- cgit v1.2.3-70-g09d2 From 242831eb15a06fa4414eaa705fdc6dd432ab98d1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 27 May 2013 12:58:46 +0200 Subject: Memory hotplug / ACPI: Simplify memory removal Now that the memory offlining should be taken care of by the companion device offlining code in acpi_scan_hot_remove(), the ACPI memory hotplug driver doesn't need to offline it in remove_memory() any more. Moreover, since the return value of remove_memory() is not used, it's better to make it be a void function and trigger a BUG() if the memory scheduled for removal is not offline. Change the code in accordance with the above observations. Signed-off-by: Rafael J. Wysocki Reviewed-by: Toshi Kani --- drivers/acpi/acpi_memhotplug.c | 13 ++------ include/linux/memory_hotplug.h | 2 +- mm/memory_hotplug.c | 71 +++++------------------------------------- 3 files changed, 12 insertions(+), 74 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 5590db12028..c711d114404 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -271,13 +271,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) return 0; } -static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) +static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device) { acpi_handle handle = mem_device->device->handle; - int result = 0, nid; struct acpi_memory_info *info, *n; - - nid = acpi_get_node(handle); + int nid = acpi_get_node(handle); list_for_each_entry_safe(info, n, &mem_device->res_list, list) { if (!info->enabled) @@ -287,15 +285,10 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device) nid = memory_add_physaddr_to_nid(info->start_addr); acpi_unbind_memory_blocks(info, handle); - result = remove_memory(nid, info->start_addr, info->length); - if (result) - return result; - + remove_memory(nid, info->start_addr, info->length); list_del(&info->list); kfree(info); } - - return result; } static void acpi_memory_device_free(struct acpi_memory_device *mem_device) diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index ae5480a0096..00569fb4ed6 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -252,7 +252,7 @@ extern int add_memory(int nid, u64 start, u64 size); extern int arch_add_memory(int nid, u64 start, u64 size); extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); extern bool is_memblock_offlined(struct memory_block *mem); -extern int remove_memory(int nid, u64 start, u64 size); +extern void remove_memory(int nid, u64 start, u64 size); extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, int nr_pages); extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms); diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a39841d240e..7026fbc42aa 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1670,24 +1670,6 @@ int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, } #ifdef CONFIG_MEMORY_HOTREMOVE -/** - * offline_memory_block_cb - callback function for offlining memory block - * @mem: the memory block to be offlined - * @arg: buffer to hold error msg - * - * Always return 0, and put the error msg in arg if any. - */ -static int offline_memory_block_cb(struct memory_block *mem, void *arg) -{ - int *ret = arg; - int error = device_offline(&mem->dev); - - if (error != 0 && *ret == 0) - *ret = error; - - return 0; -} - static int is_memblock_offlined_cb(struct memory_block *mem, void *arg) { int ret = !is_memblock_offlined(mem); @@ -1813,54 +1795,22 @@ void try_offline_node(int nid) } EXPORT_SYMBOL(try_offline_node); -int __ref remove_memory(int nid, u64 start, u64 size) +void __ref remove_memory(int nid, u64 start, u64 size) { - unsigned long start_pfn, end_pfn; - int ret = 0; - int retry = 1; - - start_pfn = PFN_DOWN(start); - end_pfn = PFN_UP(start + size - 1); - - /* - * When CONFIG_MEMCG is on, one memory block may be used by other - * blocks to store page cgroup when onlining pages. But we don't know - * in what order pages are onlined. So we iterate twice to offline - * memory: - * 1st iterate: offline every non primary memory block. - * 2nd iterate: offline primary (i.e. first added) memory block. - */ -repeat: - walk_memory_range(start_pfn, end_pfn, &ret, - offline_memory_block_cb); - if (ret) { - if (!retry) - return ret; - - retry = 0; - ret = 0; - goto repeat; - } + int ret; lock_memory_hotplug(); /* - * we have offlined all memory blocks like this: - * 1. lock memory hotplug - * 2. offline a memory block - * 3. unlock memory hotplug - * - * repeat step1-3 to offline the memory block. All memory blocks - * must be offlined before removing memory. But we don't hold the - * lock in the whole operation. So we should check whether all - * memory blocks are offlined. + * All memory blocks must be offlined before removing memory. Check + * whether all memory blocks in question are offline and trigger a BUG() + * if this is not the case. */ - - ret = walk_memory_range(start_pfn, end_pfn, NULL, + ret = walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1), NULL, is_memblock_offlined_cb); if (ret) { unlock_memory_hotplug(); - return ret; + BUG(); } /* remove memmap entry */ @@ -1871,17 +1821,12 @@ repeat: try_offline_node(nid); unlock_memory_hotplug(); - - return 0; } #else int offline_pages(unsigned long start_pfn, unsigned long nr_pages) { return -EINVAL; } -int remove_memory(int nid, u64 start, u64 size) -{ - return -EINVAL; -} +void remove_memory(int nid, u64 start, u64 size) {} #endif /* CONFIG_MEMORY_HOTREMOVE */ EXPORT_SYMBOL_GPL(remove_memory); -- cgit v1.2.3-70-g09d2 From f6f57f605eecd4f6a9b59b55bf91c50fe7b52186 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 30 May 2013 09:59:00 +0800 Subject: ACPICA: Change an exception code for the ASL UnLoad() operator Change the exception code for the case where the input DdbHandle is invalid from AE_BAD_PARAMETER to the more appropriate AE_AML_OPERAND_TYPE. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index d93b70be60a..a689aacae2b 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -588,7 +588,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) || (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* Get the table index from the ddb_handle */ -- cgit v1.2.3-70-g09d2 From e1405ca5ebf1068a0d62afd2fec8f0354038147a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 30 May 2013 09:59:21 +0800 Subject: ACPICA: Add BIOS error interface for predefined name validation support BIOS error message for errors found in predefined names. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acmacros.h | 10 ++++---- drivers/acpi/acpica/acutils.h | 6 +++++ drivers/acpi/acpica/utxferror.c | 51 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 59 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 53666bd9193..530a2f8c125 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -374,10 +374,11 @@ * the plist contains a set of parens to allow variable-length lists. * These macros are used for both the debug and non-debug versions of the code. */ -#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e); -#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e); -#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist -#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist +#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e); +#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e); +#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist +#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist +#define ACPI_BIOS_ERROR_PREDEFINED(plist) acpi_ut_predefined_bios_error plist #else @@ -387,6 +388,7 @@ #define ACPI_ERROR_METHOD(s, n, p, e) #define ACPI_WARN_PREDEFINED(plist) #define ACPI_INFO_PREDEFINED(plist) +#define ACPI_BIOS_ERROR_PREDEFINED(plist) #endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 202f4f12d3e..19e5cf72ab6 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -670,6 +670,12 @@ acpi_ut_predefined_info(const char *module_name, u32 line_number, char *pathname, u8 node_flags, const char *format, ...); +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_bios_error(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...); + void acpi_ut_namespace_error(const char *module_name, u32 line_number, diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 976b6c734fc..61a2c1704cc 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -82,8 +82,8 @@ extern FILE *acpi_gbl_output_file; #define ACPI_MSG_EXCEPTION "ACPI Exception: " #define ACPI_MSG_WARNING "ACPI Warning: " #define ACPI_MSG_INFO "ACPI: " -#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Bug: Error: " -#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Bug: Warning: " +#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Error (bug): " +#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Warning (bug): " /* * Common message suffix */ @@ -325,7 +325,7 @@ acpi_ut_predefined_warning(const char *module_name, return; } - acpi_os_printf(ACPI_MSG_WARNING "For %s: ", pathname); + acpi_os_printf(ACPI_MSG_WARNING "%s: ", pathname); va_start(arg_list, format); acpi_os_vprintf(format, arg_list); @@ -367,7 +367,50 @@ acpi_ut_predefined_info(const char *module_name, return; } - acpi_os_printf(ACPI_MSG_INFO "For %s: ", pathname); + acpi_os_printf(ACPI_MSG_INFO "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_bios_error + * + * 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 + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: BIOS error message for predefined names. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_bios_error(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_BIOS_ERROR "%s: ", pathname); va_start(arg_list, format); acpi_os_vprintf(format, arg_list); -- cgit v1.2.3-70-g09d2 From 29a241cc02110b8b2259fd72719b8cadc03909be Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 30 May 2013 10:00:01 +0800 Subject: ACPICA: Add argument typechecking for all predefined ACPI names Fully implements typechecking on all incoming arguments for all predefined names. This ensures that ACPI-related drivers are passing the correct number of arguments, each of the correct object type. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + drivers/acpi/acpica/aclocal.h | 17 --- drivers/acpi/acpica/acnamesp.h | 43 +++--- drivers/acpi/acpica/acpredef.h | 4 +- drivers/acpi/acpica/acstruct.h | 40 ++++-- drivers/acpi/acpica/evgpe.c | 1 - drivers/acpi/acpica/evregion.c | 2 +- drivers/acpi/acpica/hwxface.c | 6 +- drivers/acpi/acpica/nsarguments.c | 294 ++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/nseval.c | 247 ++++++++++++++++++-------------- drivers/acpi/acpica/nsinit.c | 7 +- drivers/acpi/acpica/nspredef.c | 201 ++++++-------------------- drivers/acpi/acpica/nsprepkg.c | 76 +++++----- drivers/acpi/acpica/nsrepair.c | 50 +++---- drivers/acpi/acpica/nsrepair2.c | 87 +++++------ drivers/acpi/acpica/nsxfeval.c | 162 ++++++++++++++++----- drivers/acpi/acpica/psxface.c | 14 +- drivers/acpi/acpica/rsutils.c | 2 +- drivers/acpi/acpica/uteval.c | 2 +- drivers/acpi/acpica/utpredef.c | 16 +-- include/acpi/acconfig.h | 4 +- 21 files changed, 800 insertions(+), 476 deletions(-) create mode 100644 drivers/acpi/acpica/nsarguments.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 7ddf29eca9f..29b3dab401e 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -83,6 +83,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o acpi-y += \ nsaccess.o \ nsalloc.o \ + nsarguments.o \ nsconvert.o \ nsdump.o \ nseval.o \ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index d5bfbd331bf..dfed26545ba 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -362,23 +362,6 @@ union acpi_predefined_info { #pragma pack() -/* Data block used during object validation */ - -struct acpi_predefined_data { - char *pathname; - const union acpi_predefined_info *predefined; - union acpi_operand_object *parent_package; - struct acpi_namespace_node *node; - u32 flags; - u32 return_btype; - u8 node_flags; -}; - -/* Defines for Flags field above */ - -#define ACPI_OBJECT_REPAIRED 1 -#define ACPI_OBJECT_WRAPPED 2 - /* Return object auto-repair info */ typedef acpi_status(*acpi_object_converter) (union acpi_operand_object diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index d2e491876bc..b83dc32a5ae 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -223,22 +223,33 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); void acpi_ns_exec_module_code_list(void); /* - * nspredef - Support for predefined/reserved names + * nsarguments - Argument count/type checking for predefined/reserved names */ -acpi_status -acpi_ns_check_predefined_names(struct acpi_namespace_node *node, - u32 user_param_count, - acpi_status return_status, - union acpi_operand_object **return_object); +void +acpi_ns_check_argument_count(char *pathname, + struct acpi_namespace_node *node, + u32 user_param_count, + const union acpi_predefined_info *info); void -acpi_ns_check_parameter_count(char *pathname, +acpi_ns_check_acpi_compliance(char *pathname, struct acpi_namespace_node *node, - u32 user_param_count, - const union acpi_predefined_info *info); + const union acpi_predefined_info *predefined); + +void acpi_ns_check_argument_types(struct acpi_evaluate_info *info); + +/* + * nspredef - Return value checking for predefined/reserved names + */ +acpi_status +acpi_ns_check_return_value(struct acpi_namespace_node *node, + struct acpi_evaluate_info *info, + u32 user_param_count, + acpi_status return_status, + union acpi_operand_object **return_object); acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, +acpi_ns_check_object_type(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index); @@ -246,7 +257,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, * nsprepkg - Validation of predefined name packages */ acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, +acpi_ns_check_package(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); /* @@ -308,24 +319,24 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node, * predefined methods/objects */ acpi_status -acpi_ns_simple_repair(struct acpi_predefined_data *data, +acpi_ns_simple_repair(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr); acpi_status -acpi_ns_wrap_with_package(struct acpi_predefined_data *data, +acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, union acpi_operand_object *original_object, union acpi_operand_object **obj_desc_ptr); acpi_status -acpi_ns_repair_null_element(struct acpi_predefined_data *data, +acpi_ns_repair_null_element(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr); void -acpi_ns_remove_null_elements(struct acpi_predefined_data *data, +acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, u8 package_type, union acpi_operand_object *obj_desc); @@ -334,7 +345,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, * predefined methods/objects */ acpi_status -acpi_ns_complex_repairs(struct acpi_predefined_data *data, +acpi_ns_complex_repairs(struct acpi_evaluate_info *info, struct acpi_namespace_node *node, acpi_status validate_status, union acpi_operand_object **return_object_ptr); diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index b22b70944fd..f600aded726 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -128,8 +128,8 @@ enum acpi_return_package_types { #define ARG_COUNT_IS_MINIMUM 0x8000 #define METHOD_MAX_ARG_TYPE ACPI_TYPE_PACKAGE -#define METHOD_GET_COUNT(arg_list) (arg_list & METHOD_ARG_MASK) -#define METHOD_GET_NEXT_ARG(arg_list) (arg_list >> METHOD_ARG_BIT_WIDTH) +#define METHOD_GET_ARG_COUNT(arg_list) ((arg_list) & METHOD_ARG_MASK) +#define METHOD_GET_NEXT_TYPE(arg_list) (((arg_list) >>= METHOD_ARG_BIT_WIDTH) & METHOD_ARG_MASK) /* Macros used to build the predefined info table */ diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index 7896d85876c..fc83c0a5ca7 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -178,25 +178,41 @@ union acpi_aml_operands { }; /* - * Structure used to pass object evaluation parameters. + * Structure used to pass object evaluation information and parameters. * Purpose is to reduce CPU stack use. */ struct acpi_evaluate_info { - struct acpi_namespace_node *prefix_node; - char *pathname; - union acpi_operand_object *obj_desc; - union acpi_operand_object **parameters; - struct acpi_namespace_node *resolved_node; - union acpi_operand_object *return_object; - u8 param_count; - u8 pass_number; - u8 return_object_type; - u8 flags; + /* The first 3 elements are passed by the caller to acpi_ns_evaluate */ + + struct acpi_namespace_node *prefix_node; /* Input: starting node */ + char *relative_pathname; /* Input: path relative to prefix_node */ + union acpi_operand_object **parameters; /* Input: argument list */ + + struct acpi_namespace_node *node; /* Resolved node (prefix_node:relative_pathname) */ + union acpi_operand_object *obj_desc; /* Object attached to the resolved node */ + char *full_pathname; /* Full pathname of the resolved node */ + + const union acpi_predefined_info *predefined; /* Used if Node is a predefined name */ + union acpi_operand_object *return_object; /* Object returned from the evaluation */ + union acpi_operand_object *parent_package; /* Used if return object is a Package */ + + u32 return_flags; /* Used for return value analysis */ + u32 return_btype; /* Bitmapped type of the returned object */ + u16 param_count; /* Count of the input argument list */ + u8 pass_number; /* Parser pass number */ + u8 return_object_type; /* Object type of the returned object */ + u8 node_flags; /* Same as Node->Flags */ + u8 flags; /* General flags */ }; /* Values for Flags above */ -#define ACPI_IGNORE_RETURN_VALUE 1 +#define ACPI_IGNORE_RETURN_VALUE 1 + +/* Defines for return_flags field above */ + +#define ACPI_OBJECT_REPAIRED 1 +#define ACPI_OBJECT_WRAPPED 2 /* Info used by acpi_ns_initialize_devices */ diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index a493b528f8f..ae50d6cc535 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -579,7 +579,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) (local_gpe_event_info->dispatch. method_node))); } - break; default: diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 6555e350fc1..8ae8f5b33bd 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -532,7 +532,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) } info->prefix_node = region_obj2->extra.method_REG; - info->pathname = NULL; + info->relative_pathname = NULL; info->parameters = args; info->flags = ACPI_IGNORE_RETURN_VALUE; diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 04c2e16f2c0..f4224e6f4e7 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -495,7 +495,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) * Evaluate the \_Sx namespace object containing the register values * for this state */ - info->pathname = + info->relative_pathname = ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { @@ -506,7 +506,7 @@ 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)); + info->relative_pathname)); status = AE_AML_NO_RETURN_VALUE; goto cleanup; } @@ -565,7 +565,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While evaluating Sleep State [%s]", - info->pathname)); + info->relative_pathname)); } ACPI_FREE(info); diff --git a/drivers/acpi/acpica/nsarguments.c b/drivers/acpi/acpica/nsarguments.c new file mode 100644 index 00000000000..74b24c82707 --- /dev/null +++ b/drivers/acpi/acpica/nsarguments.c @@ -0,0 +1,294 @@ +/****************************************************************************** + * + * Module Name: nsarguments - Validation of args for ACPI predefined methods + * + *****************************************************************************/ + +/* + * 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 +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_NAMESPACE +ACPI_MODULE_NAME("nsarguments") + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_argument_types + * + * PARAMETERS: info - Method execution information block + * + * RETURN: None + * + * DESCRIPTION: Check the incoming argument count and all argument types + * against the argument type list for a predefined name. + * + ******************************************************************************/ +void acpi_ns_check_argument_types(struct acpi_evaluate_info *info) +{ + u16 arg_type_list; + u8 arg_count; + u8 arg_type; + u8 user_arg_type; + u32 i; + + /* If not a predefined name, cannot typecheck args */ + + if (!info->predefined) { + return; + } + + arg_type_list = info->predefined->info.argument_list; + arg_count = METHOD_GET_ARG_COUNT(arg_type_list); + + /* Typecheck all arguments */ + + for (i = 0; ((i < arg_count) && (i < info->param_count)); i++) { + arg_type = METHOD_GET_NEXT_TYPE(arg_type_list); + user_arg_type = info->parameters[i]->common.type; + + if (user_arg_type != arg_type) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + ACPI_WARN_ALWAYS, + "Argument #%u type mismatch - " + "Found [%s], ACPI requires [%s]", + (i + 1), + acpi_ut_get_type_name + (user_arg_type), + acpi_ut_get_type_name(arg_type))); + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_acpi_compliance + * + * PARAMETERS: pathname - Full pathname to the node (for error msgs) + * node - Namespace node for the method/object + * predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a + * predefined name is what is expected (matches what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +acpi_ns_check_acpi_compliance(char *pathname, + struct acpi_namespace_node *node, + const union acpi_predefined_info *predefined) +{ + u32 aml_param_count; + u32 required_param_count; + + if (!predefined) { + return; + } + + /* Get the ACPI-required arg count from the predefined info table */ + + required_param_count = + METHOD_GET_ARG_COUNT(predefined->info.argument_list); + + /* + * If this object is not a control method, we can check if the ACPI + * spec requires that it be a method. + */ + if (node->type != ACPI_TYPE_METHOD) { + if (required_param_count > 0) { + + /* Object requires args, must be implemented as a method */ + + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Object (%s) must be a control method with %u arguments", + acpi_ut_get_type_name(node-> + type), + required_param_count)); + } else if (!required_param_count + && !predefined->info.expected_btypes) { + + /* Object requires no args and no return value, must be a method */ + + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Object (%s) must be a control method " + "with no arguments and no return value", + acpi_ut_get_type_name(node-> + type))); + } + + return; + } + + /* + * This is a control method. + * Check that the ASL/AML-defined parameter count for this method + * matches the ACPI-required parameter count + * + * Some methods are allowed to have a "minimum" number of args (_SCP) + * because their definition in ACPI has changed over time. + * + * Note: These are BIOS errors in the declaration of the object + */ + aml_param_count = node->object->method.param_count; + + if (aml_param_count < required_param_count) { + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "ASL declared %u, ACPI requires %u", + aml_param_count, + required_param_count)); + } else if ((aml_param_count > required_param_count) + && !(predefined->info. + argument_list & ARG_COUNT_IS_MINIMUM)) { + ACPI_BIOS_ERROR_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "ASL declared %u, ACPI requires %u", + aml_param_count, + required_param_count)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_check_argument_count + * + * PARAMETERS: pathname - Full pathname to the node (for error msgs) + * node - Namespace node for the method/object + * user_param_count - Number of args passed in by the caller + * predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that incoming argument count matches the declared + * parameter count (in the ASL/AML) for an object. + * + ******************************************************************************/ + +void +acpi_ns_check_argument_count(char *pathname, + struct acpi_namespace_node *node, + u32 user_param_count, + const union acpi_predefined_info *predefined) +{ + u32 aml_param_count; + u32 required_param_count; + + if (!predefined) { + /* + * Not a predefined name. Check the incoming user argument count + * against the count that is specified in the method/object. + */ + if (node->type != ACPI_TYPE_METHOD) { + if (user_param_count) { + ACPI_INFO_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "%u arguments were passed to a non-method ACPI object (%s)", + user_param_count, + acpi_ut_get_type_name + (node->type))); + } + + return; + } + + /* + * This is a control method. Check the parameter count. + * We can only check the incoming argument count against the + * argument count declared for the method in the ASL/AML. + * + * Emit a message if too few or too many arguments have been passed + * by the caller. + * + * Note: Too many arguments will not cause the method to + * fail. However, the method will fail if there are too few + * arguments and the method attempts to use one of the missing ones. + */ + aml_param_count = node->object->method.param_count; + + if (user_param_count < aml_param_count) { + ACPI_WARN_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "Caller passed %u, method requires %u", + user_param_count, + aml_param_count)); + } else if (user_param_count > aml_param_count) { + ACPI_INFO_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Excess arguments - " + "Caller passed %u, method requires %u", + user_param_count, + aml_param_count)); + } + + return; + } + + /* + * This is a predefined name. Validate the user-supplied parameter + * count against the ACPI specification. We don't validate against + * the method itself because what is important here is that the + * caller is in conformance with the spec. (The arg count for the + * method was checked against the ACPI spec earlier.) + * + * Some methods are allowed to have a "minimum" number of args (_SCP) + * because their definition in ACPI has changed over time. + */ + required_param_count = + METHOD_GET_ARG_COUNT(predefined->info.argument_list); + + if (user_param_count < required_param_count) { + ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "Caller passed %u, ACPI requires %u", + user_param_count, required_param_count)); + } else if ((user_param_count > required_param_count) && + !(predefined->info.argument_list & ARG_COUNT_IS_MINIMUM)) { + ACPI_INFO_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "Caller passed %u, ACPI requires %u", + user_param_count, required_param_count)); + } +} diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index b61db69d567..18108bc2e51 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -61,7 +61,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * * PARAMETERS: info - Evaluation info block, contains: * prefix_node - Prefix or Method/Object Node to execute - * pathname - Name of method to execute, If NULL, the + * relative_path - Name of method to execute, If NULL, the * Node is the object to execute * parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be @@ -82,10 +82,9 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * ******************************************************************************/ -acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; - struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(ns_evaluate); @@ -93,83 +92,138 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Initialize the return value to an invalid object */ - - info->return_object = NULL; - info->param_count = 0; - - if (!info->resolved_node) { + if (!info->node) { /* - * Get the actual namespace node for the target object if we need to. - * Handles these cases: + * Get the actual namespace node for the target object if we + * need to. Handles these cases: * - * 1) Null node, Pathname (absolute path) - * 2) Node, Pathname (path relative to Node) - * 3) Node, Null Pathname + * 1) Null node, valid pathname from root (absolute path) + * 2) Node and valid pathname (path relative to Node) + * 3) Node, Null pathname */ - status = acpi_ns_get_node(info->prefix_node, info->pathname, - ACPI_NS_NO_UPSEARCH, - &info->resolved_node); + status = + acpi_ns_get_node(info->prefix_node, info->relative_pathname, + ACPI_NS_NO_UPSEARCH, &info->node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* - * For a method alias, we must grab the actual method node so that proper - * scoping context will be established before execution. + * For a method alias, we must grab the actual method node so that + * proper scoping context will be established before execution. */ - if (acpi_ns_get_type(info->resolved_node) == - ACPI_TYPE_LOCAL_METHOD_ALIAS) { - info->resolved_node = + if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->node = ACPI_CAST_PTR(struct acpi_namespace_node, - info->resolved_node->object); + info->node->object); + } + + /* Complete the info block initialization */ + + info->return_object = NULL; + info->node_flags = info->node->flags; + info->obj_desc = acpi_ns_get_attached_object(info->node); + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", + info->relative_pathname, info->node, + acpi_ns_get_attached_object(info->node))); + + /* Get info if we have a predefined name (_HID, etc.) */ + + info->predefined = + acpi_ut_match_predefined_method(info->node->name.ascii); + + /* Get the full pathname to the object, for use in warning messages */ + + info->full_pathname = acpi_ns_get_external_pathname(info->node); + if (!info->full_pathname) { + return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, - info->resolved_node, - acpi_ns_get_attached_object(info->resolved_node))); + /* Count the number of arguments being passed in */ + + info->param_count = 0; + if (info->parameters) { + while (info->parameters[info->param_count]) { + info->param_count++; + } + + /* Warn on impossible argument count */ + + if (info->param_count > ACPI_METHOD_NUM_ARGS) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + ACPI_WARN_ALWAYS, + "Excess arguments (%u) - using only %u", + info->param_count, + ACPI_METHOD_NUM_ARGS)); + + info->param_count = ACPI_METHOD_NUM_ARGS; + } + } + + /* + * For predefined names: Check that the declared argument count + * matches the ACPI spec -- otherwise this is a BIOS error. + */ + acpi_ns_check_acpi_compliance(info->full_pathname, info->node, + info->predefined); + + /* + * For all names: Check that the incoming argument count for + * this method/object matches the actual ASL/AML definition. + */ + acpi_ns_check_argument_count(info->full_pathname, info->node, + info->param_count, info->predefined); - node = info->resolved_node; + /* For predefined names: Typecheck all incoming arguments */ + + acpi_ns_check_argument_types(info); /* - * Two major cases here: + * Three major evaluation cases: * - * 1) The object is a control method -- execute it - * 2) The object is not a method -- just return it's current value + * 1) Object types that cannot be evaluated by definition + * 2) The object is a control method -- execute it + * 3) The object is not a method -- just return it's current value */ - if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { + switch (acpi_ns_get_type(info->node)) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_LOCAL_SCOPE: + /* + * 1) Disallow evaluation of certain object types. For these, + * object evaluation is undefined and not supported. + */ + ACPI_ERROR((AE_INFO, + "%s: Evaluation of object type [%s] is not supported", + info->full_pathname, + acpi_ut_get_type_name(info->node->type))); + + status = AE_TYPE; + goto cleanup; + + case ACPI_TYPE_METHOD: /* - * 1) Object is a control method - execute it + * 2) Object is a control method - execute it */ /* Verify that there is a method object associated with this node */ - info->obj_desc = - acpi_ns_get_attached_object(info->resolved_node); if (!info->obj_desc) { ACPI_ERROR((AE_INFO, - "Control method has no attached sub-object")); - return_ACPI_STATUS(AE_NULL_OBJECT); + "%s: Method has no attached sub-object", + info->full_pathname)); + status = AE_NULL_OBJECT; + goto cleanup; } - /* Count the number of arguments being passed to the method */ - - if (info->parameters) { - while (info->parameters[info->param_count]) { - if (info->param_count > ACPI_METHOD_MAX_ARG) { - return_ACPI_STATUS(AE_LIMIT); - } - info->param_count++; - } - } - - - ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", - ACPI_LV_INFO, _COMPONENT); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Method at AML address %p Length %X\n", + "**** Execute method [%s] at AML address %p length %X\n", + info->full_pathname, info->obj_desc->method.aml_start + 1, info->obj_desc->method.aml_length - 1)); @@ -184,81 +238,61 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) acpi_ex_enter_interpreter(); status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); - } else { + break; + + default: /* - * 2) Object is not a method, return its current value - * - * Disallow certain object types. For these, "evaluation" is undefined. + * 3) All other non-method objects -- get the current object value */ - switch (info->resolved_node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_EVENT: - case ACPI_TYPE_MUTEX: - case ACPI_TYPE_REGION: - case ACPI_TYPE_THERMAL: - case ACPI_TYPE_LOCAL_SCOPE: - - ACPI_ERROR((AE_INFO, - "[%4.4s] Evaluation of object type [%s] is not supported", - info->resolved_node->name.ascii, - acpi_ut_get_type_name(info->resolved_node-> - type))); - - return_ACPI_STATUS(AE_TYPE); - - default: - break; - } /* - * Objects require additional resolution steps (e.g., the Node may be - * a field that must be read, etc.) -- we can't just grab the object - * out of the node. + * Some objects require additional resolution steps (e.g., the Node + * may be a field that must be read, etc.) -- we can't just grab + * the object out of the node. * * Use resolve_node_to_value() to get the associated value. * * NOTE: we can get away with passing in NULL for a walk state because - * resolved_node is guaranteed to not be a reference to either a method + * the Node is guaranteed to not be a reference to either a method * local or a method argument (because this interface is never called * from a running method.) * * Even though we do not directly invoke the interpreter for object - * resolution, we must lock it because we could access an opregion. - * The opregion access code assumes that the interpreter is locked. + * resolution, we must lock it because we could access an op_region. + * The op_region access code assumes that the interpreter is locked. */ acpi_ex_enter_interpreter(); - /* Function has a strange interface */ + /* TBD: resolve_node_to_value has a strange interface, fix */ + + info->return_object = + ACPI_CAST_PTR(union acpi_operand_object, info->node); status = - acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR + (struct acpi_namespace_node, + &info->return_object), NULL); acpi_ex_exit_interpreter(); - /* - * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed - * in resolved_node. - */ - if (ACPI_SUCCESS(status)) { - status = AE_CTRL_RETURN_VALUE; - info->return_object = - ACPI_CAST_PTR(union acpi_operand_object, - info->resolved_node); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Returning object %p [%s]\n", - info->return_object, - acpi_ut_get_object_type_name(info-> - return_object))); + if (ACPI_FAILURE(status)) { + goto cleanup; } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n", + info->return_object, + acpi_ut_get_object_type_name(info-> + return_object))); + + status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ + break; } /* - * Check input argument count against the ASL-defined count for a method. - * Also check predefined names: argument count and return value against - * the ACPI specification. Some incorrect return value types are repaired. + * For predefined names, check the return value against the ACPI + * specification. Some incorrect return value types are repaired. */ - (void)acpi_ns_check_predefined_names(node, info->param_count, - status, &info->return_object); + (void)acpi_ns_check_return_value(info->node, info, info->param_count, + status, &info->return_object); /* Check if there is a return value that must be dealt with */ @@ -278,12 +312,15 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "*** Completed evaluation of object %s ***\n", - info->pathname)); + info->relative_pathname)); + cleanup: /* * Namespace was unlocked by the handling acpi_ns* function, so we - * just return + * just free the pathname and return */ + ACPI_FREE(info->full_pathname); + info->full_pathname = NULL; return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 46f0f83417a..23e426f7fd1 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -176,7 +176,7 @@ acpi_status acpi_ns_initialize_devices(void) * part of the ACPI specification. */ info.evaluate_info->prefix_node = acpi_gbl_root_node; - info.evaluate_info->pathname = METHOD_NAME__INI; + info.evaluate_info->relative_pathname = METHOD_NAME__INI; info.evaluate_info->parameters = NULL; info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE; @@ -560,7 +560,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); info->prefix_node = device_node; - info->pathname = METHOD_NAME__INI; + info->relative_pathname = METHOD_NAME__INI; info->parameters = NULL; info->flags = ACPI_IGNORE_RETURN_VALUE; @@ -574,8 +574,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, /* Ignore error and move on to next device */ - char *scope_name = - acpi_ns_get_external_pathname(info->resolved_node); + char *scope_name = acpi_ns_get_external_pathname(info->node); ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", scope_name)); diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 8a52916148c..7ab7ddbe3de 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -61,28 +61,29 @@ ACPI_MODULE_NAME("nspredef") * There are several areas that are validated: * * 1) The number of input arguments as defined by the method/object in the - * ASL is validated against the ACPI specification. + * ASL is validated against the ACPI specification. * 2) The type of the return object (if any) is validated against the ACPI - * specification. + * specification. * 3) For returned package objects, the count of package elements is - * validated, as well as the type of each package element. Nested - * packages are supported. + * validated, as well as the type of each package element. Nested + * packages are supported. * * For any problems found, a warning message is issued. * ******************************************************************************/ /* Local prototypes */ static acpi_status -acpi_ns_check_reference(struct acpi_predefined_data *data, +acpi_ns_check_reference(struct acpi_evaluate_info *info, union acpi_operand_object *return_object); static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); /******************************************************************************* * - * FUNCTION: acpi_ns_check_predefined_names + * FUNCTION: acpi_ns_check_return_value * * PARAMETERS: node - Namespace node for the method/object + * info - Method execution information block * user_param_count - Number of parameters actually passed * return_status - Status from the object evaluation * return_object_ptr - Pointer to the object returned from the @@ -90,44 +91,28 @@ static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object); * * RETURN: Status * - * DESCRIPTION: Check an ACPI name for a match in the predefined name list. + * DESCRIPTION: Check the value returned from a predefined name. * ******************************************************************************/ acpi_status -acpi_ns_check_predefined_names(struct acpi_namespace_node *node, - u32 user_param_count, - acpi_status return_status, - union acpi_operand_object **return_object_ptr) +acpi_ns_check_return_value(struct acpi_namespace_node *node, + struct acpi_evaluate_info *info, + u32 user_param_count, + acpi_status return_status, + union acpi_operand_object **return_object_ptr) { - acpi_status status = AE_OK; + acpi_status status; const union acpi_predefined_info *predefined; char *pathname; - struct acpi_predefined_data *data; - - /* Match the name for this method/object against the predefined list */ - - predefined = acpi_ut_match_predefined_method(node->name.ascii); - /* Get the full pathname to the object, for use in warning messages */ - - pathname = acpi_ns_get_external_pathname(node); - if (!pathname) { - return (AE_OK); /* Could not get pathname, ignore */ - } - - /* - * Check that the parameter count for this method matches the ASL - * definition. For predefined names, ensure that both the caller and - * the method itself are in accordance with the ACPI specification. - */ - acpi_ns_check_parameter_count(pathname, node, user_param_count, - predefined); + predefined = info->predefined; + pathname = info->full_pathname; /* If not a predefined name, we cannot validate the return object */ if (!predefined) { - goto cleanup; + return (AE_OK); } /* @@ -135,7 +120,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, * validate the return object */ if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { - goto cleanup; + return (AE_OK); } /* @@ -154,25 +139,14 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, if (acpi_gbl_disable_auto_repair || (!predefined->info.expected_btypes) || (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { - goto cleanup; - } - - /* Create the parameter data block for object validation */ - - data = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_predefined_data)); - if (!data) { - goto cleanup; + return (AE_OK); } - data->predefined = predefined; - data->node = node; - data->node_flags = node->flags; - data->pathname = pathname; /* * Check that the type of the main return object is what is expected * for this predefined name */ - status = acpi_ns_check_object_type(data, return_object_ptr, + status = acpi_ns_check_object_type(info, return_object_ptr, predefined->info.expected_btypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE(status)) { @@ -184,8 +158,8 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, * Note: Package may have been newly created by call above. */ if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { - data->parent_package = *return_object_ptr; - status = acpi_ns_check_package(data, return_object_ptr); + info->parent_package = *return_object_ptr; + status = acpi_ns_check_package(info, return_object_ptr); if (ACPI_FAILURE(status)) { goto exit; } @@ -199,7 +173,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, * performed on a per-name basis, i.e., the code is specific to * particular predefined names. */ - status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); + status = acpi_ns_complex_repairs(info, node, status, return_object_ptr); exit: /* @@ -207,112 +181,18 @@ exit: * or more objects, mark the parent node to suppress further warning * messages during the next evaluation of the same method/object. */ - if (ACPI_FAILURE(status) || (data->flags & ACPI_OBJECT_REPAIRED)) { + if (ACPI_FAILURE(status) || (info->return_flags & ACPI_OBJECT_REPAIRED)) { node->flags |= ANOBJ_EVALUATED; } - ACPI_FREE(data); -cleanup: - ACPI_FREE(pathname); return (status); } -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_parameter_count - * - * PARAMETERS: pathname - Full pathname to the node (for error msgs) - * node - Namespace node for the method/object - * user_param_count - Number of args passed in by the caller - * predefined - Pointer to entry in predefined name table - * - * RETURN: None - * - * DESCRIPTION: Check that the declared (in ASL/AML) parameter count for a - * predefined name is what is expected (i.e., what is defined in - * the ACPI specification for this predefined name.) - * - ******************************************************************************/ - -void -acpi_ns_check_parameter_count(char *pathname, - struct acpi_namespace_node *node, - u32 user_param_count, - const union acpi_predefined_info *predefined) -{ - u32 param_count; - u32 required_params_current; - u32 required_params_old; - - /* Methods have 0-7 parameters. All other types have zero. */ - - param_count = 0; - if (node->type == ACPI_TYPE_METHOD) { - param_count = node->object->method.param_count; - } - - if (!predefined) { - /* - * Check the parameter count for non-predefined methods/objects. - * - * Warning if too few or too many arguments have been passed by the - * caller. An incorrect number of arguments may not cause the method - * to fail. However, the method will fail if there are too few - * arguments and the method attempts to use one of the missing ones. - */ - if (user_param_count < param_count) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Insufficient arguments - needs %u, found %u", - param_count, user_param_count)); - } else if (user_param_count > param_count) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Excess arguments - needs %u, found %u", - param_count, user_param_count)); - } - return; - } - - /* - * Validate the user-supplied parameter count. - * Allow two different legal argument counts (_SCP, etc.) - */ - required_params_current = - predefined->info.argument_list & METHOD_ARG_MASK; - required_params_old = - predefined->info.argument_list >> METHOD_ARG_BIT_WIDTH; - - if (user_param_count != ACPI_UINT32_MAX) { - if ((user_param_count != required_params_current) && - (user_param_count != required_params_old)) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Parameter count mismatch - " - "caller passed %u, ACPI requires %u", - user_param_count, - required_params_current)); - } - } - - /* - * Check that the ASL-defined parameter count is what is expected for - * this predefined name (parameter count as defined by the ACPI - * specification) - */ - if ((param_count != required_params_current) && - (param_count != required_params_old)) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, node->flags, - "Parameter count mismatch - ASL declared %u, ACPI requires %u", - param_count, required_params_current)); - } -} - /******************************************************************************* * * FUNCTION: acpi_ns_check_object_type * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * expected_btypes - Bitmap of expected return type(s) @@ -328,7 +208,7 @@ acpi_ns_check_parameter_count(char *pathname, ******************************************************************************/ acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, +acpi_ns_check_object_type(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index) { @@ -340,7 +220,8 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, if (return_object && ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Invalid return type - Found a Namespace node [%4.4s] type %s", return_object->node.name.ascii, acpi_ut_get_type_name(return_object->node. @@ -356,8 +237,8 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, * from all of the predefined names (including elements of returned * packages) */ - data->return_btype = acpi_ns_get_bitmapped_type(return_object); - if (data->return_btype == ACPI_RTYPE_ANY) { + info->return_btype = acpi_ns_get_bitmapped_type(return_object); + if (info->return_btype == ACPI_RTYPE_ANY) { /* Not one of the supported objects, must be incorrect */ goto type_error_exit; @@ -365,16 +246,18 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, /* For reference objects, check that the reference type is correct */ - if ((data->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { - status = acpi_ns_check_reference(data, return_object); + if ((info->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) { + status = acpi_ns_check_reference(info, return_object); return (status); } /* Attempt simple repair of the returned object if necessary */ - status = acpi_ns_simple_repair(data, expected_btypes, + status = acpi_ns_simple_repair(info, expected_btypes, package_index, return_object_ptr); - return (status); + if (ACPI_SUCCESS(status)) { + return (AE_OK); /* Successful repair */ + } type_error_exit: @@ -383,12 +266,14 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, acpi_ut_get_expected_return_types(type_buffer, expected_btypes); if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Return type mismatch - found %s, expected %s", acpi_ut_get_object_type_name (return_object), type_buffer)); } else { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Return Package type mismatch at index %u - " "found %s, expected %s", package_index, acpi_ut_get_object_type_name @@ -402,7 +287,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_reference * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object - Object returned from the evaluation of a * method or object * @@ -415,7 +300,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_reference(struct acpi_predefined_data *data, +acpi_ns_check_reference(struct acpi_evaluate_info *info, union acpi_operand_object *return_object) { @@ -428,7 +313,7 @@ acpi_ns_check_reference(struct acpi_predefined_data *data, return (AE_OK); } - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Return type mismatch - unexpected reference object type [%s] %2.2X", acpi_ut_get_reference_name(return_object), return_object->reference.class)); diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 77cdd539de1..ab2a3f477e1 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -51,12 +51,12 @@ ACPI_MODULE_NAME("nsprepkg") /* Local prototypes */ static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, +acpi_ns_check_package_list(struct acpi_evaluate_info *info, 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, +acpi_ns_check_package_elements(struct acpi_evaluate_info *info, union acpi_operand_object **elements, u8 type1, u32 count1, @@ -66,7 +66,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_package * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -78,7 +78,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, ******************************************************************************/ acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, +acpi_ns_check_package(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -93,18 +93,18 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* The package info for this name is in the next table entry */ - package = data->predefined + 1; + package = info->predefined + 1; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s Validating return Package of Type %X, Count %X\n", - data->pathname, package->ret_info.type, + info->full_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, + acpi_ns_remove_null_elements(info, package->ret_info.type, return_object); /* Extract package count and elements array */ @@ -121,7 +121,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data, return (AE_OK); } - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Return Package has no elements (empty)")); return (AE_AML_OPERAND_VALUE); @@ -150,13 +151,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Return Package is larger than needed - " "found %u, expected %u\n", - data->pathname, count, + info->full_pathname, count, expected_count)); } /* Validate all elements of the returned package */ - status = acpi_ns_check_package_elements(data, elements, + status = acpi_ns_check_package_elements(info, elements, package->ret_info. object_type1, package->ret_info. @@ -174,7 +175,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, * elements must be of the same type */ for (i = 0; i < count; i++) { - status = acpi_ns_check_object_type(data, elements, + status = acpi_ns_check_object_type(info, elements, package->ret_info. object_type1, i); if (ACPI_FAILURE(status)) { @@ -206,7 +207,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* These are the required package elements (0, 1, or 2) */ status = - acpi_ns_check_object_type(data, elements, + acpi_ns_check_object_type(info, elements, package-> ret_info3. object_type[i], @@ -218,7 +219,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* These are the optional package elements */ status = - acpi_ns_check_object_type(data, elements, + acpi_ns_check_object_type(info, elements, package-> ret_info3. tail_object_type, @@ -235,7 +236,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* First element is the (Integer) revision */ - status = acpi_ns_check_object_type(data, elements, + status = acpi_ns_check_object_type(info, elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE(status)) { return (status); @@ -247,14 +248,14 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Examine the sub-packages */ status = - acpi_ns_check_package_list(data, package, elements, count); + acpi_ns_check_package_list(info, 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, + status = acpi_ns_check_object_type(info, elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE(status)) { return (status); @@ -275,7 +276,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Examine the sub-packages */ status = - acpi_ns_check_package_list(data, package, elements, count); + acpi_ns_check_package_list(info, package, elements, count); break; case ACPI_PTYPE2: @@ -300,7 +301,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Create the new outer package and populate it */ status = - acpi_ns_wrap_with_package(data, return_object, + acpi_ns_wrap_with_package(info, return_object, return_object_ptr); if (ACPI_FAILURE(status)) { return (status); @@ -316,14 +317,15 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Examine the sub-packages */ status = - acpi_ns_check_package_list(data, package, elements, count); + acpi_ns_check_package_list(info, 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, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Invalid internal return type in table entry: %X", package->ret_info.type)); @@ -336,7 +338,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Error exit for the case with an incorrect package count */ - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Return Package is too small - found %u elements, expected %u", count, expected_count)); @@ -347,7 +349,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_package_list * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * package - Pointer to package-specific info for method * elements - Element list of parent package. All elements * of this list should be of type Package. @@ -360,7 +362,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, +acpi_ns_check_package_list(struct acpi_evaluate_info *info, const union acpi_predefined_info *package, union acpi_operand_object **elements, u32 count) { @@ -381,11 +383,11 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, for (i = 0; i < count; i++) { sub_package = *elements; sub_elements = sub_package->package.elements; - data->parent_package = sub_package; + info->parent_package = sub_package; /* Each sub-object must be of type Package */ - status = acpi_ns_check_object_type(data, &sub_package, + status = acpi_ns_check_object_type(info, &sub_package, ACPI_RTYPE_PACKAGE, i); if (ACPI_FAILURE(status)) { return (status); @@ -393,7 +395,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, /* Examine the different types of expected sub-packages */ - data->parent_package = sub_package; + info->parent_package = sub_package; switch (package->ret_info.type) { case ACPI_PTYPE2: case ACPI_PTYPE2_PKG_COUNT: @@ -408,7 +410,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, } status = - acpi_ns_check_package_elements(data, sub_elements, + acpi_ns_check_package_elements(info, sub_elements, package->ret_info. object_type1, package->ret_info. @@ -434,7 +436,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, } status = - acpi_ns_check_package_elements(data, sub_elements, + acpi_ns_check_package_elements(info, sub_elements, package->ret_info. object_type1, package->ret_info. @@ -463,7 +465,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, for (j = 0; j < expected_count; j++) { status = - acpi_ns_check_object_type(data, + acpi_ns_check_object_type(info, &sub_elements[j], package-> ret_info2. @@ -487,7 +489,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, /* Check the type of each sub-package element */ status = - acpi_ns_check_package_elements(data, sub_elements, + acpi_ns_check_package_elements(info, sub_elements, package->ret_info. object_type1, sub_package->package. @@ -503,7 +505,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, * 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, + status = acpi_ns_check_object_type(info, sub_elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE(status)) { @@ -537,7 +539,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, /* Check the type of each sub-package element */ status = - acpi_ns_check_package_elements(data, + acpi_ns_check_package_elements(info, (sub_elements + 1), package->ret_info. object_type1, @@ -562,7 +564,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, /* The sub-package count was smaller than required */ - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Return Sub-Package[%u] is too small - found %u elements, expected %u", i, sub_package->package.count, expected_count)); @@ -573,7 +575,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_package_elements * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * elements - Pointer to the package elements array * type1 - Object type for first group * count1 - Count for first group @@ -589,7 +591,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, +acpi_ns_check_package_elements(struct acpi_evaluate_info *info, union acpi_operand_object **elements, u8 type1, u32 count1, @@ -605,7 +607,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * The second group can have a count of zero. */ for (i = 0; i < count1; i++) { - status = acpi_ns_check_object_type(data, this_element, + status = acpi_ns_check_object_type(info, this_element, type1, i + start_index); if (ACPI_FAILURE(status)) { return (status); @@ -614,7 +616,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, } for (i = 0; i < count2; i++) { - status = acpi_ns_check_object_type(data, this_element, + status = acpi_ns_check_object_type(info, this_element, type2, (i + count1 + start_index)); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 18f02e4ece0..89caef04691 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -130,7 +130,7 @@ static const struct acpi_simple_repair_info acpi_object_repair_info[] = { * * FUNCTION: acpi_ns_simple_repair * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * expected_btypes - Object types expected * package_index - Index of object within parent package (if * applicable - ACPI_NOT_PACKAGE_ELEMENT @@ -146,7 +146,7 @@ static const struct acpi_simple_repair_info acpi_object_repair_info[] = { ******************************************************************************/ acpi_status -acpi_ns_simple_repair(struct acpi_predefined_data *data, +acpi_ns_simple_repair(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) @@ -162,12 +162,12 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, * Special repairs for certain names that are in the repair table. * Check if this name is in the list of repairable names. */ - predefined = acpi_ns_match_simple_repair(data->node, - data->return_btype, + predefined = acpi_ns_match_simple_repair(info->node, + info->return_btype, package_index); if (predefined) { if (!return_object) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, ACPI_WARN_ALWAYS, "Missing expected return value")); } @@ -191,7 +191,7 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, * Do not perform simple object repair unless the return type is not * expected. */ - if (data->return_btype & expected_btypes) { + if (info->return_btype & expected_btypes) { return (AE_OK); } @@ -211,7 +211,7 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, */ if (!return_object) { if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, ACPI_WARN_ALWAYS, "Missing expected return value")); @@ -247,14 +247,14 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, * for correct contents (expected object type or types). */ status = - acpi_ns_wrap_with_package(data, return_object, &new_object); + acpi_ns_wrap_with_package(info, return_object, &new_object); if (ACPI_SUCCESS(status)) { /* * The original object just had its reference count * incremented for being inserted into the new package. */ *return_object_ptr = new_object; /* New Package object */ - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } } @@ -277,7 +277,7 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, * package object as part of the repair, we don't need to * change the reference count. */ - if (!(data->flags & ACPI_OBJECT_WRAPPED)) { + if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) { new_object->common.reference_count = return_object->common.reference_count; @@ -288,14 +288,14 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted %s to expected %s at Package index %u\n", - data->pathname, + info->full_pathname, acpi_ut_get_object_type_name(return_object), acpi_ut_get_object_type_name(new_object), package_index)); } else { ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted %s to expected %s\n", - data->pathname, + info->full_pathname, acpi_ut_get_object_type_name(return_object), acpi_ut_get_object_type_name(new_object))); } @@ -304,7 +304,7 @@ acpi_ns_simple_repair(struct acpi_predefined_data *data, acpi_ut_remove_reference(return_object); *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -359,7 +359,7 @@ static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct * * FUNCTION: acpi_ns_repair_null_element * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * expected_btypes - Object types expected * package_index - Index of object within parent package (if * applicable - ACPI_NOT_PACKAGE_ELEMENT @@ -374,7 +374,7 @@ static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct ******************************************************************************/ acpi_status -acpi_ns_repair_null_element(struct acpi_predefined_data *data, +acpi_ns_repair_null_element(struct acpi_evaluate_info * info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) @@ -424,16 +424,16 @@ acpi_ns_repair_null_element(struct acpi_predefined_data *data, /* Set the reference count according to the parent Package object */ new_object->common.reference_count = - data->parent_package->common.reference_count; + info->parent_package->common.reference_count; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted NULL package element to expected %s at index %u\n", - data->pathname, + info->full_pathname, acpi_ut_get_object_type_name(new_object), package_index)); *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -441,7 +441,7 @@ acpi_ns_repair_null_element(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_remove_null_elements * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * package_type - An acpi_return_package_types value * obj_desc - A Package object * @@ -454,7 +454,7 @@ acpi_ns_repair_null_element(struct acpi_predefined_data *data, *****************************************************************************/ void -acpi_ns_remove_null_elements(struct acpi_predefined_data *data, +acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, u8 package_type, union acpi_operand_object *obj_desc) { @@ -511,7 +511,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, if (new_count < count) { ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Found and removed %u NULL elements\n", - data->pathname, (count - new_count))); + info->full_pathname, (count - new_count))); /* NULL terminate list and update the package count */ @@ -524,7 +524,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_wrap_with_package * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * original_object - Pointer to the object to repair. * obj_desc_ptr - The new package object is returned here * @@ -545,7 +545,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data, ******************************************************************************/ acpi_status -acpi_ns_wrap_with_package(struct acpi_predefined_data *data, +acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, union acpi_operand_object *original_object, union acpi_operand_object **obj_desc_ptr) { @@ -566,12 +566,12 @@ acpi_ns_wrap_with_package(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Wrapped %s with expected Package object\n", - data->pathname, + info->full_pathname, acpi_ut_get_object_type_name(original_object))); /* Return the new object in the object pointer */ *obj_desc_ptr = pkg_obj_desc; - data->flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; + info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; return (AE_OK); } diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 149e9b9c2c1..39acc4e6b38 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -54,7 +54,7 @@ ACPI_MODULE_NAME("nsrepair2") * be repaired on a per-name basis. */ typedef -acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data, +acpi_status(*acpi_repair_function) (struct acpi_evaluate_info * info, union acpi_operand_object **return_object_ptr); @@ -71,31 +71,31 @@ static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct *node); static acpi_status -acpi_ns_repair_ALR(struct acpi_predefined_data *data, +acpi_ns_repair_ALR(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_CID(struct acpi_predefined_data *data, +acpi_ns_repair_CID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_FDE(struct acpi_predefined_data *data, +acpi_ns_repair_FDE(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_HID(struct acpi_predefined_data *data, +acpi_ns_repair_HID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_PSS(struct acpi_predefined_data *data, +acpi_ns_repair_PSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_repair_TSS(struct acpi_predefined_data *data, +acpi_ns_repair_TSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); static acpi_status -acpi_ns_check_sorted_list(struct acpi_predefined_data *data, +acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, u32 expected_count, u32 sort_index, @@ -150,7 +150,7 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = { * * FUNCTION: acpi_ns_complex_repairs * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * node - Namespace node for the method/object * validate_status - Original status of earlier validation * return_object_ptr - Pointer to the object returned from the @@ -165,7 +165,7 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = { *****************************************************************************/ acpi_status -acpi_ns_complex_repairs(struct acpi_predefined_data *data, +acpi_ns_complex_repairs(struct acpi_evaluate_info *info, struct acpi_namespace_node *node, acpi_status validate_status, union acpi_operand_object **return_object_ptr) @@ -180,7 +180,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, return (validate_status); } - status = predefined->repair_function(data, return_object_ptr); + status = predefined->repair_function(info, return_object_ptr); return (status); } @@ -219,7 +219,7 @@ static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct * * FUNCTION: acpi_ns_repair_ALR * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -231,13 +231,13 @@ static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct *****************************************************************************/ static acpi_status -acpi_ns_repair_ALR(struct acpi_predefined_data *data, +acpi_ns_repair_ALR(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status; - status = acpi_ns_check_sorted_list(data, return_object, 2, 1, + status = acpi_ns_check_sorted_list(info, return_object, 2, 1, ACPI_SORT_ASCENDING, "AmbientIlluminance"); @@ -248,7 +248,7 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_FDE * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -262,7 +262,7 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_FDE(struct acpi_predefined_data *data, +acpi_ns_repair_FDE(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -285,8 +285,8 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, /* We can only repair if we have exactly 5 BYTEs */ if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Incorrect return buffer length %u, expected %u", return_object->buffer.length, ACPI_FDE_DWORD_BUFFER_SIZE)); @@ -316,7 +316,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s Expanded Byte Buffer to expected DWord Buffer\n", - data->pathname)); + info->full_pathname)); break; default: @@ -328,7 +328,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, acpi_ut_remove_reference(return_object); *return_object_ptr = buffer_object; - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -336,7 +336,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_CID * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -349,7 +349,7 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_CID(struct acpi_predefined_data *data, +acpi_ns_repair_CID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { acpi_status status; @@ -362,7 +362,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, /* Check for _CID as a simple string */ if (return_object->common.type == ACPI_TYPE_STRING) { - status = acpi_ns_repair_HID(data, return_object_ptr); + status = acpi_ns_repair_HID(info, return_object_ptr); return (status); } @@ -379,7 +379,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, original_element = *element_ptr; original_ref_count = original_element->common.reference_count; - status = acpi_ns_repair_HID(data, element_ptr); + status = acpi_ns_repair_HID(info, element_ptr); if (ACPI_FAILURE(status)) { return (status); } @@ -406,7 +406,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_HID * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -418,7 +418,7 @@ acpi_ns_repair_CID(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_HID(struct acpi_predefined_data *data, +acpi_ns_repair_HID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -435,12 +435,13 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, } if (return_object->string.length == 0) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "Invalid zero-length _HID or _CID string")); /* Return AE_OK anyway, let driver handle it */ - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } @@ -464,7 +465,7 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Removed invalid leading asterisk\n", - data->pathname)); + info->full_pathname)); } /* @@ -488,7 +489,7 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_TSS * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -500,7 +501,7 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_TSS(struct acpi_predefined_data *data, +acpi_ns_repair_TSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -515,13 +516,13 @@ acpi_ns_repair_TSS(struct acpi_predefined_data *data, * In this case, it is best to just return the _TSS package as-is. * (May, 2011) */ - status = - acpi_ns_get_node(data->node, "^_PSS", ACPI_NS_NO_UPSEARCH, &node); + status = acpi_ns_get_node(info->node, "^_PSS", + ACPI_NS_NO_UPSEARCH, &node); if (ACPI_SUCCESS(status)) { return (AE_OK); } - status = acpi_ns_check_sorted_list(data, return_object, 5, 1, + status = acpi_ns_check_sorted_list(info, return_object, 5, 1, ACPI_SORT_DESCENDING, "PowerDissipation"); @@ -532,7 +533,7 @@ acpi_ns_repair_TSS(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_repair_PSS * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -546,7 +547,7 @@ acpi_ns_repair_TSS(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_repair_PSS(struct acpi_predefined_data *data, +acpi_ns_repair_PSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; @@ -564,7 +565,7 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, * incorrectly sorted, sort it. We sort by cpu_frequency, since this * should be proportional to the power. */ - status = acpi_ns_check_sorted_list(data, return_object, 6, 0, + status = acpi_ns_check_sorted_list(info, return_object, 6, 0, ACPI_SORT_DESCENDING, "CpuFrequency"); if (ACPI_FAILURE(status)) { @@ -584,8 +585,8 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, obj_desc = elements[1]; /* Index1 = power_dissipation */ if ((u32) obj_desc->integer.value > previous_value) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, "SubPackage[%u,%u] - suspicious power dissipation values", i - 1, i)); } @@ -601,7 +602,7 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_sorted_list * - * PARAMETERS: data - Pointer to validation data structure + * PARAMETERS: info - Method execution information block * return_object - Pointer to the top-level returned object * expected_count - Minimum length of each sub-package * sort_index - Sub-package entry to sort on @@ -617,7 +618,7 @@ acpi_ns_repair_PSS(struct acpi_predefined_data *data, *****************************************************************************/ static acpi_status -acpi_ns_check_sorted_list(struct acpi_predefined_data *data, +acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, u32 expected_count, u32 sort_index, @@ -689,11 +690,11 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data, outer_element_count, sort_index, sort_direction); - data->flags |= ACPI_OBJECT_REPAIRED; + info->return_flags |= ACPI_OBJECT_REPAIRED; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Repaired unsorted list - now sorted by %s\n", - data->pathname, sort_key_name)); + info->full_pathname, sort_key_name)); return (AE_OK); } diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index fc69949151b..82bec40d450 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -187,8 +187,6 @@ acpi_evaluate_object(acpi_handle handle, return_ACPI_STATUS(AE_NO_MEMORY); } - info->pathname = pathname; - /* Convert and validate the device handle */ info->prefix_node = acpi_ns_validate_handle(handle); @@ -198,17 +196,64 @@ acpi_evaluate_object(acpi_handle handle, } /* - * If there are parameters to be passed to a control method, the external - * objects must all be converted to internal objects + * Get the actual namespace node for the target object. + * Handles these cases: + * + * 1) Null node, valid pathname from root (absolute path) + * 2) Node and valid pathname (path relative to Node) + * 3) Node, Null pathname + */ + if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { + + /* The path is fully qualified, just evaluate by name */ + + info->prefix_node = NULL; + } else if (!handle) { + /* + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error. + */ + if (!pathname) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Both Handle and Pathname are NULL")); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", + pathname)); + } + + status = AE_BAD_PARAMETER; + goto cleanup; + } + + info->relative_pathname = pathname; + + /* + * Convert all external objects passed as arguments to the + * internal version(s). */ if (external_params && external_params->count) { + info->param_count = (u16)external_params->count; + + /* Warn on impossible argument count */ + + if (info->param_count > ACPI_METHOD_NUM_ARGS) { + ACPI_WARN_PREDEFINED((AE_INFO, pathname, + ACPI_WARN_ALWAYS, + "Excess arguments (%u) - using only %u", + info->param_count, + ACPI_METHOD_NUM_ARGS)); + + info->param_count = ACPI_METHOD_NUM_ARGS; + } + /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) - external_params-> - count + + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info-> + param_count + 1) * sizeof(void *)); if (!info->parameters) { status = AE_NO_MEMORY; @@ -217,7 +262,7 @@ acpi_evaluate_object(acpi_handle handle, /* Convert each external object in the list to an internal object */ - for (i = 0; i < external_params->count; i++) { + for (i = 0; i < info->param_count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], @@ -227,43 +272,96 @@ acpi_evaluate_object(acpi_handle handle, goto cleanup; } } - info->parameters[external_params->count] = NULL; + + info->parameters[info->param_count] = NULL; } +#if 0 + /* - * Three major cases: - * 1) Fully qualified pathname - * 2) No handle, not fully qualified pathname (error) - * 3) Valid handle + * Begin incoming argument count analysis. Check for too few args + * and too many args. */ - if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { - /* The path is fully qualified, just evaluate by name */ + switch (acpi_ns_get_type(info->node)) { + case ACPI_TYPE_METHOD: + + /* Check incoming argument count against the method definition */ + + if (info->obj_desc->method.param_count > info->param_count) { + ACPI_ERROR((AE_INFO, + "Insufficient arguments (%u) - %u are required", + info->param_count, + info->obj_desc->method.param_count)); + + status = AE_MISSING_ARGUMENTS; + goto cleanup; + } + + else if (info->obj_desc->method.param_count < info->param_count) { + ACPI_WARNING((AE_INFO, + "Excess arguments (%u) - only %u are required", + info->param_count, + info->obj_desc->method.param_count)); + + /* Just pass the required number of arguments */ + + info->param_count = info->obj_desc->method.param_count; + } - info->prefix_node = NULL; - status = acpi_ns_evaluate(info); - } else if (!handle) { /* - * A handle is optional iff a fully qualified pathname is specified. - * Since we've already handled fully qualified names above, this is - * an error + * Any incoming external objects to be passed as arguments to the + * method must be converted to internal objects */ - if (!pathname) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Both Handle and Pathname are NULL")); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Null Handle with relative pathname [%s]", - pathname)); + if (info->param_count) { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + */ + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + info-> + param_count + + 1) * + sizeof(void *)); + if (!info->parameters) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Convert each external object in the list to an internal object */ + + for (i = 0; i < info->param_count; i++) { + status = + acpi_ut_copy_eobject_to_iobject + (&external_params->pointer[i], + &info->parameters[i]); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + } + + info->parameters[info->param_count] = NULL; } + break; - status = AE_BAD_PARAMETER; - } else { - /* We have a namespace a node and a possible relative path */ + default: - status = acpi_ns_evaluate(info); + /* Warn if arguments passed to an object that is not a method */ + + if (info->param_count) { + ACPI_WARNING((AE_INFO, + "%u arguments were passed to a non-method ACPI object", + info->param_count)); + } + break; } +#endif + + /* Now we can evaluate the object */ + + status = acpi_ns_evaluate(info); + /* * If we are expecting a return value, and all went well above, * copy the return value to an external object. diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index f6825426896..11b99ab20bb 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -125,7 +125,7 @@ static void acpi_ps_start_trace(struct acpi_evaluate_info *info) } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { + (acpi_gbl_trace_method_name != info->node->name.integer)) { goto exit; } @@ -170,7 +170,7 @@ static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { + (acpi_gbl_trace_method_name != info->node->name.integer)) { goto exit; } @@ -226,15 +226,14 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* Validate the Info and method Node */ - if (!info || !info->resolved_node) { + if (!info || !info->node) { return_ACPI_STATUS(AE_NULL_ENTRY); } /* Init for new method, wait on concurrency semaphore */ status = - acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc, - NULL); + acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -253,8 +252,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", - info->resolved_node->name.ascii, info->resolved_node, - info->obj_desc)); + info->node->name.ascii, info->node, info->obj_desc)); /* Create and init a Root Node */ @@ -275,7 +273,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) goto cleanup; } - status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, + status = acpi_ds_init_aml_walk(walk_state, op, info->node, info->obj_desc->method.aml_start, info->obj_desc->method.aml_length, info, info->pass_number); diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index a44953c6f75..59bdf37164b 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -736,7 +736,7 @@ acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, } info->prefix_node = node; - info->pathname = METHOD_NAME__SRS; + info->relative_pathname = METHOD_NAME__SRS; info->parameters = args; info->flags = ACPI_IGNORE_RETURN_VALUE; diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index c3f3a7e7bdc..1673dddc9cd 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -87,7 +87,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node * prefix_node, } info->prefix_node = prefix_node; - info->pathname = path; + info->relative_pathname = path; /* Evaluate the object/method */ diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c index 29459479148..2b1ce4cd320 100644 --- a/drivers/acpi/acpica/utpredef.c +++ b/drivers/acpi/acpica/utpredef.c @@ -147,6 +147,11 @@ void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes) u32 i; u32 j; + if (!expected_btypes) { + ACPI_STRCPY(buffer, "NONE"); + return; + } + j = 1; buffer[0] = 0; this_rtype = ACPI_RTYPE_INTEGER; @@ -328,9 +333,7 @@ static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types) /* First field in the types list is the count of args to follow */ - arg_count = (argument_types & METHOD_ARG_MASK); - argument_types >>= METHOD_ARG_BIT_WIDTH; - + arg_count = METHOD_GET_ARG_COUNT(argument_types); if (arg_count > METHOD_PREDEF_ARGS_MAX) { printf("**** Invalid argument count (%u) " "in predefined info structure\n", arg_count); @@ -340,7 +343,8 @@ static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types) /* Get each argument from the list, convert to ascii, store to buffer */ for (i = 0; i < arg_count; i++) { - this_argument_type = (argument_types & METHOD_ARG_MASK); + this_argument_type = METHOD_GET_NEXT_TYPE(argument_types); + if (!this_argument_type || (this_argument_type > METHOD_MAX_ARG_TYPE)) { printf("**** Invalid argument type (%u) " @@ -351,10 +355,6 @@ static u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types) strcat(buffer, ut_external_type_names[this_argument_type] + sub_index); - - /* Shift to next argument type field */ - - argument_types >>= METHOD_ARG_BIT_WIDTH; sub_index = 0; } diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index 14ceff788c4..1c16f821434 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -219,8 +219,8 @@ * *****************************************************************************/ -#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */ -#define ACPI_DB_LINE_BUFFER_SIZE 512 +#define ACPI_DEBUGGER_MAX_ARGS ACPI_METHOD_NUM_ARGS + 4 /* Max command line arguments */ +#define ACPI_DB_LINE_BUFFER_SIZE 512 #define ACPI_DEBUGGER_COMMAND_PROMPT '-' #define ACPI_DEBUGGER_EXECUTE_PROMPT '%' -- cgit v1.2.3-70-g09d2 From 43e5318f34f2cafd8734ac20d0e7bb0dd5c2538e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 30 May 2013 10:00:53 +0800 Subject: ACPICA: Predefined name support: Remove unused local variable "Pathname" is no longer used. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nspredef.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 7ab7ddbe3de..5c83a8b1c15 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -104,13 +104,10 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node, { acpi_status status; const union acpi_predefined_info *predefined; - char *pathname; - - predefined = info->predefined; - pathname = info->full_pathname; /* If not a predefined name, we cannot validate the return object */ + predefined = info->predefined; if (!predefined) { return (AE_OK); } -- cgit v1.2.3-70-g09d2 From 8f4f5e781554493230ce9b2d5a979eef637aa109 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 30 May 2013 10:02:13 +0800 Subject: ACPICA: Update for "orphan" embedded controller _REG method support This refers to _REG methods under the EC device that have no corresponding operation region. This is allowed by the ACPI specification. This update removes a dependency on having an ECDT table, and will execute an orphan _REG method as long as the handler for the EC is installed at the EC device node (not the namespace root). Rui Zhang (original update), Bob Moore (update/integrate). Signed-off-by: Zhang Rui Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evregion.c | 61 +++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 40 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 8ae8f5b33bd..cea14d6fc76 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -54,7 +54,8 @@ extern u8 acpi_gbl_default_address_spaces[]; /* Local prototypes */ -static void acpi_ev_orphan_ec_reg_method(void); +static void +acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node); static acpi_status acpi_ev_reg_run(acpi_handle obj_handle, @@ -612,7 +613,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, /* Special case for EC: handle "orphan" _REG methods with no region */ if (space_id == ACPI_ADR_SPACE_EC) { - acpi_ev_orphan_ec_reg_method(); + acpi_ev_orphan_ec_reg_method(node); } return_ACPI_STATUS(status); @@ -681,7 +682,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, * * FUNCTION: acpi_ev_orphan_ec_reg_method * - * PARAMETERS: None + * PARAMETERS: ec_device_node - Namespace node for an EC device * * RETURN: None * @@ -693,37 +694,27 @@ acpi_ev_reg_run(acpi_handle obj_handle, * detected by providing a _REG method object underneath the * Embedded Controller device." * - * To quickly access the EC device, we use the EC_ID that appears - * within the ECDT. Otherwise, we would need to perform a time- - * consuming namespace walk, executing _HID methods to find the - * EC device. + * To quickly access the EC device, we use the ec_device_node used + * during EC handler installation. Otherwise, we would need to + * perform a time consuming namespace walk, executing _HID + * methods to find the EC device. + * + * MUTEX: Assumes the namespace is locked * ******************************************************************************/ -static void acpi_ev_orphan_ec_reg_method(void) +static void +acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node) { - struct acpi_table_ecdt *table; + acpi_handle reg_method; + struct acpi_namespace_node *next_node; acpi_status status; struct acpi_object_list args; union acpi_object objects[2]; - struct acpi_namespace_node *ec_device_node; - struct acpi_namespace_node *reg_method; - struct acpi_namespace_node *next_node; ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method); - /* Get the ECDT (if present in system) */ - - status = acpi_get_table(ACPI_SIG_ECDT, 0, - ACPI_CAST_INDIRECT_PTR(struct acpi_table_header, - &table)); - if (ACPI_FAILURE(status)) { - return_VOID; - } - - /* We need a valid EC_ID string */ - - if (!(*table->id)) { + if (!ec_device_node) { return_VOID; } @@ -731,22 +722,11 @@ static void acpi_ev_orphan_ec_reg_method(void) (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - /* Get a handle to the EC device referenced in the ECDT */ - - status = acpi_get_handle(NULL, - ACPI_CAST_PTR(char, table->id), - ACPI_CAST_PTR(acpi_handle, &ec_device_node)); - if (ACPI_FAILURE(status)) { - goto exit; - } - /* Get a handle to a _REG method immediately under the EC device */ - status = acpi_get_handle(ec_device_node, - METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle, - ®_method)); + status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method); if (ACPI_FAILURE(status)) { - goto exit; + goto exit; /* There is no _REG method present */ } /* @@ -754,19 +734,20 @@ static void acpi_ev_orphan_ec_reg_method(void) * this scope with the Embedded Controller space ID. Otherwise, it * will already have been executed. Note, this allows for Regions * with other space IDs to be present; but the code below will then - * execute the _REG method with the EC space ID argument. + * execute the _REG method with the embedded_control space_ID argument. */ next_node = acpi_ns_get_next_node(ec_device_node, NULL); while (next_node) { if ((next_node->type == ACPI_TYPE_REGION) && (next_node->object) && (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) { - goto exit; /* Do not execute _REG */ + goto exit; /* Do not execute the _REG */ } + next_node = acpi_ns_get_next_node(ec_device_node, next_node); } - /* Evaluate the _REG(EC,Connect) method */ + /* Evaluate the _REG(embedded_control,Connect) method */ args.count = 2; args.pointer = objects; -- cgit v1.2.3-70-g09d2 From 173a5a4c909789fcd57d00355d2237618a3824a4 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 31 May 2013 11:36:08 +0800 Subject: ACPI / processor: Fix potential NULL pointer dereference in acpi_processor_add() In acpi_processor_add(), get_cpu_device() may return NULL in some cases which is then passed to acpi_bind_one() and that will case a NULL pointer dereference to occur. Add a check to prevent that from happening. [rjw: Changelog] Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 157e7389a5f..e9b01e35ac3 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -393,6 +393,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device, per_cpu(processors, pr->id) = pr; dev = get_cpu_device(pr->id); + if (!dev) { + result = -ENODEV; + goto err; + } + result = acpi_bind_one(dev, pr->handle); if (result) goto err; -- cgit v1.2.3-70-g09d2 From 45f0a85c8258741d11bda25c0a5669c06267204a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 3 Jun 2013 21:49:52 +0200 Subject: PM / Runtime: Rework the "runtime idle" helper routine The "runtime idle" helper routine, rpm_idle(), currently ignores return values from .runtime_idle() callbacks executed by it. However, it turns out that many subsystems use pm_generic_runtime_idle() which checks the return value of the driver's callback and executes pm_runtime_suspend() for the device unless that value is not 0. If that logic is moved to rpm_idle() instead, pm_generic_runtime_idle() can be dropped and its users will not need any .runtime_idle() callbacks any more. Moreover, the PCI, SCSI, and SATA subsystems' .runtime_idle() routines, pci_pm_runtime_idle(), scsi_runtime_idle(), and ata_port_runtime_idle(), respectively, as well as a few drivers' ones may be simplified if rpm_idle() calls rpm_suspend() after 0 has been returned by the .runtime_idle() callback executed by it. To reduce overall code bloat, make the changes described above. Tested-by: Mika Westerberg Tested-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki Acked-by: Kevin Hilman Reviewed-by: Ulf Hansson Acked-by: Alan Stern --- Documentation/power/runtime_pm.txt | 5 ----- arch/arm/mach-omap2/omap_device.c | 7 +------ drivers/acpi/device_pm.c | 1 - drivers/amba/bus.c | 2 +- drivers/ata/libata-core.c | 2 +- drivers/base/platform.c | 1 - drivers/base/power/domain.c | 1 - drivers/base/power/generic_ops.c | 23 ----------------------- drivers/base/power/runtime.c | 12 +++++------- drivers/dma/intel_mid_dma.c | 2 +- drivers/gpio/gpio-langwell.c | 6 +----- drivers/i2c/i2c-core.c | 2 +- drivers/mfd/ab8500-gpadc.c | 8 +------- drivers/mmc/core/bus.c | 2 +- drivers/mmc/core/sdio_bus.c | 2 +- drivers/pci/pci-driver.c | 14 +++++--------- drivers/scsi/scsi_pm.c | 11 +++-------- drivers/sh/pm_runtime.c | 2 +- drivers/spi/spi.c | 2 +- drivers/tty/serial/mfd.c | 9 ++------- drivers/usb/core/driver.c | 3 ++- drivers/usb/core/port.c | 1 - include/linux/pm_runtime.h | 2 -- 23 files changed, 28 insertions(+), 92 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 6c9f5d9aa11..6c470c71ba2 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -660,11 +660,6 @@ Subsystems may wish to conserve code space by using the set of generic power management callbacks provided by the PM core, defined in driver/base/power/generic_ops.c: - int pm_generic_runtime_idle(struct device *dev); - - invoke the ->runtime_idle() callback provided by the driver of this - device, if defined, and call pm_runtime_suspend() for this device if the - return value is 0 or the callback is not defined - int pm_generic_runtime_suspend(struct device *dev); - invoke the ->runtime_suspend() callback provided by the driver of this device and return its result, or return -EINVAL if not defined diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index e6d230700b2..e37feb2f05a 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -591,11 +591,6 @@ static int _od_runtime_suspend(struct device *dev) return ret; } -static int _od_runtime_idle(struct device *dev) -{ - return pm_generic_runtime_idle(dev); -} - static int _od_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -653,7 +648,7 @@ static int _od_resume_noirq(struct device *dev) struct dev_pm_domain omap_device_pm_domain = { .ops = { SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, - _od_runtime_idle) + NULL) USE_PLATFORM_PM_SLEEP_OPS .suspend_noirq = _od_suspend_noirq, .resume_noirq = _od_resume_noirq, diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index bc493aa3af1..1eb8b625878 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -886,7 +886,6 @@ static struct dev_pm_domain acpi_general_pm_domain = { #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, diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index cdbad3a454a..c6707278a6b 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -284,7 +284,7 @@ static const struct dev_pm_ops amba_pm = { SET_RUNTIME_PM_OPS( amba_pm_runtime_suspend, amba_pm_runtime_resume, - pm_generic_runtime_idle + NULL ) }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 63c743baf92..84e3b62aa36 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5430,7 +5430,7 @@ static int ata_port_runtime_idle(struct device *dev) return -EBUSY; } - return pm_runtime_suspend(dev); + return 0; } static int ata_port_runtime_suspend(struct device *dev) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9eda84246ff..96a930387eb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -888,7 +888,6 @@ int platform_pm_restore(struct device *dev) static const struct dev_pm_ops platform_dev_pm_ops = { .runtime_suspend = pm_generic_runtime_suspend, .runtime_resume = pm_generic_runtime_resume, - .runtime_idle = pm_generic_runtime_idle, USE_PLATFORM_PM_SLEEP_OPS }; diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7072404c8b6..bfb8955c406 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2143,7 +2143,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd, genpd->max_off_time_changed = true; genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; - genpd->domain.ops.runtime_idle = pm_generic_runtime_idle; genpd->domain.ops.prepare = pm_genpd_prepare; genpd->domain.ops.suspend = pm_genpd_suspend; genpd->domain.ops.suspend_late = pm_genpd_suspend_late; diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index bfd898b8988..5ee030a864f 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c @@ -11,29 +11,6 @@ #include #ifdef CONFIG_PM_RUNTIME -/** - * pm_generic_runtime_idle - Generic runtime idle callback for subsystems. - * @dev: Device to handle. - * - * If PM operations are defined for the @dev's driver and they include - * ->runtime_idle(), execute it and return its error code, if nonzero. - * Otherwise, execute pm_runtime_suspend() for the device and return 0. - */ -int pm_generic_runtime_idle(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm && pm->runtime_idle) { - int ret = pm->runtime_idle(dev); - if (ret) - return ret; - } - - pm_runtime_suspend(dev); - return 0; -} -EXPORT_SYMBOL_GPL(pm_generic_runtime_idle); - /** * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems. * @dev: Device to suspend. diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index ef13ad08afb..268a3509757 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -293,11 +293,8 @@ static int rpm_idle(struct device *dev, int rpmflags) /* Pending requests need to be canceled. */ dev->power.request = RPM_REQ_NONE; - if (dev->power.no_callbacks) { - /* Assume ->runtime_idle() callback would have suspended. */ - retval = rpm_suspend(dev, rpmflags); + if (dev->power.no_callbacks) goto out; - } /* Carry out an asynchronous or a synchronous idle notification. */ if (rpmflags & RPM_ASYNC) { @@ -306,7 +303,8 @@ static int rpm_idle(struct device *dev, int rpmflags) dev->power.request_pending = true; queue_work(pm_wq, &dev->power.work); } - goto out; + trace_rpm_return_int(dev, _THIS_IP_, 0); + return 0; } dev->power.idle_notification = true; @@ -326,14 +324,14 @@ static int rpm_idle(struct device *dev, int rpmflags) callback = dev->driver->pm->runtime_idle; if (callback) - __rpm_callback(callback, dev); + retval = __rpm_callback(callback, dev); dev->power.idle_notification = false; wake_up_all(&dev->power.wait_queue); out: trace_rpm_return_int(dev, _THIS_IP_, retval); - return retval; + return retval ? retval : rpm_suspend(dev, rpmflags); } /** diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index a0de82e21a7..a975ebebea8 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c @@ -1405,7 +1405,7 @@ static int dma_runtime_idle(struct device *dev) return -EAGAIN; } - return pm_schedule_suspend(dev, 0); + return 0; } /****************************************************************************** diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index 62ef10a641c..89d0d2a3b1b 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c @@ -305,11 +305,7 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = { static int lnw_gpio_runtime_idle(struct device *dev) { - int err = pm_schedule_suspend(dev, 500); - - if (!err) - return 0; - + pm_schedule_suspend(dev, 500); return -EBUSY; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 48e31ed69db..f32ca293ae0 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -435,7 +435,7 @@ static const struct dev_pm_ops i2c_device_pm_ops = { SET_RUNTIME_PM_OPS( pm_generic_runtime_suspend, pm_generic_runtime_resume, - pm_generic_runtime_idle + NULL ) }; diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 13f7866de46..3598b0ecf8c 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -886,12 +886,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev) return ret; } -static int ab8500_gpadc_runtime_idle(struct device *dev) -{ - pm_runtime_suspend(dev); - return 0; -} - static int ab8500_gpadc_suspend(struct device *dev) { struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); @@ -1039,7 +1033,7 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) static const struct dev_pm_ops ab8500_gpadc_pm_ops = { SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, ab8500_gpadc_runtime_resume, - ab8500_gpadc_runtime_idle) + NULL) SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend, ab8500_gpadc_resume) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index e219c97a02a..9d5c7112557 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -164,7 +164,7 @@ static int mmc_runtime_resume(struct device *dev) static int mmc_runtime_idle(struct device *dev) { - return pm_runtime_suspend(dev); + return 0; } #endif /* !CONFIG_PM_RUNTIME */ diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 546c67c2bbb..6d67492a924 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -211,7 +211,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { SET_RUNTIME_PM_OPS( pm_generic_runtime_suspend, pm_generic_runtime_resume, - pm_generic_runtime_idle + NULL ) }; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 79277fb36c6..e6515e21afa 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -1050,26 +1050,22 @@ static int pci_pm_runtime_idle(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + int ret = 0; /* * If pci_dev->driver is not set (unbound), the device should * always remain in D0 regardless of the runtime PM status */ if (!pci_dev->driver) - goto out; + return 0; if (!pm) return -ENOSYS; - if (pm->runtime_idle) { - int ret = pm->runtime_idle(dev); - if (ret) - return ret; - } + if (pm->runtime_idle) + ret = pm->runtime_idle(dev); -out: - pm_runtime_suspend(dev); - return 0; + return ret; } #else /* !CONFIG_PM_RUNTIME */ diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 42539ee2cb1..4c5aabe2175 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -229,8 +229,6 @@ static int scsi_runtime_resume(struct device *dev) static int scsi_runtime_idle(struct device *dev) { - int err; - dev_dbg(dev, "scsi_runtime_idle\n"); /* Insert hooks here for targets, hosts, and transport classes */ @@ -240,14 +238,11 @@ static int scsi_runtime_idle(struct device *dev) if (sdev->request_queue->dev) { pm_runtime_mark_last_busy(dev); - err = pm_runtime_autosuspend(dev); - } else { - err = pm_runtime_suspend(dev); + pm_runtime_autosuspend(dev); + return -EBUSY; } - } else { - err = pm_runtime_suspend(dev); } - return err; + return 0; } int scsi_autopm_get_device(struct scsi_device *sdev) diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c index afe9282629b..8afa5a4589f 100644 --- a/drivers/sh/pm_runtime.c +++ b/drivers/sh/pm_runtime.c @@ -25,7 +25,7 @@ static int default_platform_runtime_idle(struct device *dev) { /* suspend synchronously to disable clocks immediately */ - return pm_runtime_suspend(dev); + return 0; } static struct dev_pm_domain default_pm_domain = { diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 32b7bb111eb..095cfaded1c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -223,7 +223,7 @@ static const struct dev_pm_ops spi_pm = { SET_RUNTIME_PM_OPS( pm_generic_runtime_suspend, pm_generic_runtime_resume, - pm_generic_runtime_idle + NULL ) }; diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 5f4765a7a5c..5dfcf3bae23 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -1248,13 +1248,8 @@ static int serial_hsu_resume(struct pci_dev *pdev) #ifdef CONFIG_PM_RUNTIME static int serial_hsu_runtime_idle(struct device *dev) { - int err; - - err = pm_schedule_suspend(dev, 500); - if (err) - return -EBUSY; - - return 0; + pm_schedule_suspend(dev, 500); + return -EBUSY; } static int serial_hsu_runtime_suspend(struct device *dev) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 6eab440e154..7609ac4aed1 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1765,7 +1765,8 @@ int usb_runtime_idle(struct device *dev) */ if (autosuspend_check(udev) == 0) pm_runtime_autosuspend(dev); - return 0; + /* Tell the core not to suspend it, though. */ + return -EBUSY; } int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index b8bad294eeb..8c1b2c50946 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -141,7 +141,6 @@ static const struct dev_pm_ops usb_port_pm_ops = { #ifdef CONFIG_PM_RUNTIME .runtime_suspend = usb_port_runtime_suspend, .runtime_resume = usb_port_runtime_resume, - .runtime_idle = pm_generic_runtime_idle, #endif }; diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 7d7e09efff9..6fa7cea25da 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -37,7 +37,6 @@ extern void pm_runtime_enable(struct device *dev); extern void __pm_runtime_disable(struct device *dev, bool check_resume); extern void pm_runtime_allow(struct device *dev); extern void pm_runtime_forbid(struct device *dev); -extern int pm_generic_runtime_idle(struct device *dev); extern int pm_generic_runtime_suspend(struct device *dev); extern int pm_generic_runtime_resume(struct device *dev); extern void pm_runtime_no_callbacks(struct device *dev); @@ -143,7 +142,6 @@ static inline bool pm_runtime_active(struct device *dev) { return true; } static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } static inline bool pm_runtime_enabled(struct device *dev) { return false; } -static inline int pm_generic_runtime_idle(struct device *dev) { return 0; } static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline void pm_runtime_no_callbacks(struct device *dev) {} -- cgit v1.2.3-70-g09d2 From d9e455f53f6fb93c764de2399c3894bbdfd2caa7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 10 Jun 2013 13:00:50 +0200 Subject: ACPI / scan: Simplify ACPI driver probing There is no particular reason why acpi_bus_driver_init() needs to be a separate function and its location with respect to its only caller, acpi_device_probe(), makes the code a bit difficult to follow. Besides, it doesn't really make sense to check if 'device' is not NULL in acpi_bus_driver_init(), because we've already dereferenced dev->driver in acpi_device_probe() at that point and, moreover, 'device' cannot be NULL then, because acpi_device_probe() is called via really_probe() (which also sets dev->driver for that matter). For these reasons, drop acpi_bus_driver_init() altogether and move the remaining code from it directly into acpi_device_probe(). Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 81 ++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 54 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b14ac46948c..4eeea226245 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -816,32 +816,40 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) acpi_device_notify); } -static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); -static int acpi_device_probe(struct device * dev) +static int acpi_device_probe(struct device *dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); int ret; - ret = acpi_bus_driver_init(acpi_dev, acpi_drv); - if (!ret) { - 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->driver = NULL; - acpi_dev->driver_data = NULL; - return ret; - } - } + if (!acpi_drv->ops.add) + return -ENOSYS; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found driver [%s] for device [%s]\n", - acpi_drv->name, acpi_dev->pnp.bus_id)); - get_device(dev); + ret = acpi_drv->ops.add(acpi_dev); + if (ret) + return ret; + + acpi_dev->driver = acpi_drv; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Driver [%s] successfully bound to device [%s]\n", + acpi_drv->name, acpi_dev->pnp.bus_id)); + + 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->driver = NULL; + acpi_dev->driver_data = NULL; + return ret; + } } - return ret; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", + acpi_drv->name, acpi_dev->pnp.bus_id)); + get_device(dev); + return 0; } static int acpi_device_remove(struct device * dev) @@ -997,41 +1005,6 @@ static void acpi_device_unregister(struct acpi_device *device) /* -------------------------------------------------------------------------- Driver Management -------------------------------------------------------------------------- */ -/** - * acpi_bus_driver_init - add a device to a driver - * @device: the device to add and initialize - * @driver: driver for the device - * - * Used to initialize a device via its device driver. Called whenever a - * driver is bound to a device. Invokes the driver's add() ops. - */ -static int -acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) -{ - int result = 0; - - if (!device || !driver) - return -EINVAL; - - if (!driver->ops.add) - return -ENOSYS; - - result = driver->ops.add(device); - if (result) - return result; - - device->driver = driver; - - /* - * TBD - Configuration Management: Assign resources to device based - * upon possible configuration and currently allocated resources. - */ - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Driver successfully bound to device\n")); - return 0; -} - /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered -- cgit v1.2.3-70-g09d2 From 88ec28603c09ccba0346c15eef64ff0b4327c9ee Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 8 Jun 2013 00:57:47 +0000 Subject: ACPICA: Split buffer dump routines into separate file To enhance configurability of ACPICA. The new file is utilities/utbuffer.c Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + drivers/acpi/acpica/utbuffer.c | 201 +++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/utdebug.c | 148 +----------------------------- 3 files changed, 203 insertions(+), 147 deletions(-) create mode 100644 drivers/acpi/acpica/utbuffer.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 29b3dab401e..474901ec01c 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -146,6 +146,7 @@ acpi-y += \ acpi-y += \ utaddress.o \ utalloc.o \ + utbuffer.o \ utcopy.o \ utexcep.o \ utdebug.o \ diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c new file mode 100644 index 00000000000..11fde93be12 --- /dev/null +++ b/drivers/acpi/acpica/utbuffer.c @@ -0,0 +1,201 @@ +/****************************************************************************** + * + * Module Name: utbuffer - Buffer dump 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 +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utbuffer") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer + * + * PARAMETERS: buffer - Buffer to dump + * count - Amount to dump, in bytes + * display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * base_offset - Beginning buffer offset (display only) + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ +void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + if (!buffer) { + acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((count < 4) || (count & 0x01)) { + display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < count) { + + /* Print current offset */ + + acpi_os_printf("%6.4X: ", (base_offset + i)); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + + /* Dump fill spaces */ + + acpi_os_printf("%*s", ((display * 2) + 1), " "); + j += display; + continue; + } + + switch (display) { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + acpi_os_printf("%02X ", + buffer[(acpi_size) i + j]); + break; + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%04X ", temp32); + break; + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%08X ", temp32); + break; + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_os_printf("%08X", temp32); + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j + + 4]); + acpi_os_printf("%08X ", temp32); + break; + } + + j += display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + acpi_os_printf(" "); + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_os_printf("\n"); + return; + } + + buf_char = buffer[(acpi_size) i + j]; + if (ACPI_IS_PRINT(buf_char)) { + acpi_os_printf("%c", buf_char); + } else { + acpi_os_printf("."); + } + } + + /* Done with that line. */ + + acpi_os_printf("\n"); + i += 16; + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_debug_dump_buffer + * + * PARAMETERS: buffer - Buffer to dump + * count - Amount to dump, in bytes + * display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * component_ID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + acpi_ut_dump_buffer(buffer, count, display, 0); +} diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index c57d9cc07ba..5796e11a067 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: utdebug - Debug print routines + * Module Name: utdebug - Debug print/trace routines * *****************************************************************************/ @@ -543,149 +543,3 @@ acpi_ut_ptr_exit(u32 line_number, } #endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_buffer - * - * PARAMETERS: buffer - Buffer to dump - * count - Amount to dump, in bytes - * display - BYTE, WORD, DWORD, or QWORD display - * offset - Beginning buffer offset (display only) - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ******************************************************************************/ - -void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset) -{ - u32 i = 0; - u32 j; - u32 temp32; - u8 buf_char; - - if (!buffer) { - acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); - return; - } - - if ((count < 4) || (count & 0x01)) { - display = DB_BYTE_DISPLAY; - } - - /* Nasty little dump buffer routine! */ - - while (i < count) { - - /* Print current offset */ - - acpi_os_printf("%6.4X: ", (base_offset + i)); - - /* Print 16 hex chars */ - - for (j = 0; j < 16;) { - if (i + j >= count) { - - /* Dump fill spaces */ - - acpi_os_printf("%*s", ((display * 2) + 1), " "); - j += display; - continue; - } - - switch (display) { - case DB_BYTE_DISPLAY: - default: /* Default is BYTE display */ - - acpi_os_printf("%02X ", - buffer[(acpi_size) i + j]); - break; - - case DB_WORD_DISPLAY: - - ACPI_MOVE_16_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%04X ", temp32); - break; - - case DB_DWORD_DISPLAY: - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%08X ", temp32); - break; - - case DB_QWORD_DISPLAY: - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j]); - acpi_os_printf("%08X", temp32); - - ACPI_MOVE_32_TO_32(&temp32, - &buffer[(acpi_size) i + j + - 4]); - acpi_os_printf("%08X ", temp32); - break; - } - - j += display; - } - - /* - * Print the ASCII equivalent characters but watch out for the bad - * unprintable ones (printable chars are 0x20 through 0x7E) - */ - acpi_os_printf(" "); - for (j = 0; j < 16; j++) { - if (i + j >= count) { - acpi_os_printf("\n"); - return; - } - - buf_char = buffer[(acpi_size) i + j]; - if (ACPI_IS_PRINT(buf_char)) { - acpi_os_printf("%c", buf_char); - } else { - acpi_os_printf("."); - } - } - - /* Done with that line. */ - - acpi_os_printf("\n"); - i += 16; - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_debug_dump_buffer - * - * PARAMETERS: buffer - Buffer to dump - * count - Amount to dump, in bytes - * display - BYTE, WORD, DWORD, or QWORD display - * component_ID - Caller's component ID - * - * RETURN: None - * - * DESCRIPTION: Generic dump buffer in both hex and ascii. - * - ******************************************************************************/ - -void -acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) -{ - - /* Only dump the buffer if tracing is enabled */ - - if (!((ACPI_LV_TABLES & acpi_dbg_level) && - (component_id & acpi_dbg_layer))) { - return; - } - - acpi_ut_dump_buffer(buffer, count, display, 0); -} -- cgit v1.2.3-70-g09d2 From b6872ff9a4785a790f9647ee2076e7e616a3bb0e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 8 Jun 2013 00:58:00 +0000 Subject: ACPICA: Split internal error msg routines to a separate file Improves configurability of ACPICA. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + drivers/acpi/acpica/acutils.h | 42 ++++++ drivers/acpi/acpica/uterror.c | 289 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/uteval.c | 2 +- drivers/acpi/acpica/utxferror.c | 277 -------------------------------------- 5 files changed, 333 insertions(+), 278 deletions(-) create mode 100644 drivers/acpi/acpica/uterror.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 474901ec01c..987bf41ec90 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -152,6 +152,7 @@ acpi-y += \ utdebug.o \ utdecode.o \ utdelete.o \ + uterror.o \ uteval.o \ utglobal.o \ utids.o \ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 19e5cf72ab6..d552036935d 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -87,6 +87,48 @@ extern const char *acpi_gbl_fc_decode[]; extern const char *acpi_gbl_pt_decode[]; #endif +/* + * For the iASL compiler case, the output is redirected to stderr so that + * any of the various ACPI errors and warnings do not appear in the output + * files, for either the compiler or disassembler portions of the tool. + */ +#ifdef ACPI_ASL_COMPILER + +#include +extern FILE *acpi_gbl_output_file; + +#define ACPI_MSG_REDIRECT_BEGIN \ + FILE *output_file = acpi_gbl_output_file; \ + acpi_os_redirect_output (stderr); + +#define ACPI_MSG_REDIRECT_END \ + acpi_os_redirect_output (output_file); + +#else +/* + * non-iASL case - no redirection, nothing to do + */ +#define ACPI_MSG_REDIRECT_BEGIN +#define ACPI_MSG_REDIRECT_END +#endif + +/* + * Common error message prefixes + */ +#define ACPI_MSG_ERROR "ACPI Error: " +#define ACPI_MSG_EXCEPTION "ACPI Exception: " +#define ACPI_MSG_WARNING "ACPI Warning: " +#define ACPI_MSG_INFO "ACPI: " + +#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Error (bug): " +#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Warning (bug): " + +/* + * Common message suffix + */ +#define ACPI_MSG_SUFFIX \ + acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) + /* Types for Resource descriptor entries */ #define ACPI_INVALID_RESOURCE 0 diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c new file mode 100644 index 00000000000..154fdcaa583 --- /dev/null +++ b/drivers/acpi/acpica/uterror.c @@ -0,0 +1,289 @@ +/******************************************************************************* + * + * Module Name: uterror - Various internal error/warning output functions + * + ******************************************************************************/ + +/* + * 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 +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("uterror") + +/* + * This module contains internal error functions that may + * be configured out. + */ +#if !defined (ACPI_NO_ERROR_MESSAGES) +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_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 + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Warnings for the predefined validation module. Messages are + * only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of error + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_warning(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_WARNING "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_info + * + * 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 + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Info messages for the predefined validation module. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_info(const char *module_name, + u32 line_number, + char *pathname, u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_INFO "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_predefined_bios_error + * + * 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 + * node_flags - From Namespace node for the method/object + * format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: BIOS error message for predefined names. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +acpi_ut_predefined_bios_error(const char *module_name, + u32 line_number, + char *pathname, + u8 node_flags, const char *format, ...) +{ + va_list arg_list; + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (node_flags & ANOBJ_EVALUATED) { + return; + } + + acpi_os_printf(ACPI_MSG_BIOS_ERROR "%s: ", pathname); + + va_start(arg_list, format); + acpi_os_vprintf(format, arg_list); + ACPI_MSG_SUFFIX; + va_end(arg_list); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_namespace_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * internal_name - Name or path of the namespace node + * lookup_status - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the NS node. + * + ******************************************************************************/ + +void +acpi_ut_namespace_error(const char *module_name, + u32 line_number, + const char *internal_name, acpi_status lookup_status) +{ + acpi_status status; + u32 bad_name; + char *name = NULL; + + ACPI_MSG_REDIRECT_BEGIN; + acpi_os_printf(ACPI_MSG_ERROR); + + if (lookup_status == AE_BAD_CHARACTER) { + + /* There is a non-ascii character in the name */ + + ACPI_MOVE_32_TO_32(&bad_name, + ACPI_CAST_PTR(u32, internal_name)); + acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name); + } else { + /* Convert path to external format */ + + status = acpi_ns_externalize_name(ACPI_UINT32_MAX, + internal_name, NULL, &name); + + /* Print target name */ + + if (ACPI_SUCCESS(status)) { + acpi_os_printf("[%s]", name); + } else { + acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); + } + + if (name) { + ACPI_FREE(name); + } + } + + acpi_os_printf(" Namespace lookup failure, %s", + acpi_format_exception(lookup_status)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_method_error + * + * PARAMETERS: module_name - Caller's module name (for error output) + * line_number - Caller's line number (for error output) + * message - Error message to use on failure + * prefix_node - Prefix relative to the path + * path - Path to the node (optional) + * method_status - Execution status + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the method. + * + ******************************************************************************/ + +void +acpi_ut_method_error(const char *module_name, + u32 line_number, + const char *message, + struct acpi_namespace_node *prefix_node, + const char *path, acpi_status method_status) +{ + acpi_status status; + struct acpi_namespace_node *node = prefix_node; + + ACPI_MSG_REDIRECT_BEGIN; + acpi_os_printf(ACPI_MSG_ERROR); + + if (path) { + status = + acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, + &node); + if (ACPI_FAILURE(status)) { + acpi_os_printf("[Could not get node by pathname]"); + } + } + + acpi_ns_print_node_pathname(node, message); + acpi_os_printf(", %s", acpi_format_exception(method_status)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 1673dddc9cd..9d6802911c0 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -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/utxferror.c b/drivers/acpi/acpica/utxferror.c index 61a2c1704cc..e966a2e47b7 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -44,7 +44,6 @@ #include #include #include "accommon.h" -#include "acnamesp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utxferror") @@ -52,43 +51,7 @@ ACPI_MODULE_NAME("utxferror") /* * This module is used for the in-kernel ACPICA as well as the ACPICA * tools/applications. - * - * For the iASL compiler case, the output is redirected to stderr so that - * any of the various ACPI errors and warnings do not appear in the output - * files, for either the compiler or disassembler portions of the tool. - */ -#ifdef ACPI_ASL_COMPILER -#include -extern FILE *acpi_gbl_output_file; - -#define ACPI_MSG_REDIRECT_BEGIN \ - FILE *output_file = acpi_gbl_output_file; \ - acpi_os_redirect_output (stderr); - -#define ACPI_MSG_REDIRECT_END \ - acpi_os_redirect_output (output_file); - -#else -/* - * non-iASL case - no redirection, nothing to do - */ -#define ACPI_MSG_REDIRECT_BEGIN -#define ACPI_MSG_REDIRECT_END -#endif -/* - * Common message prefixes */ -#define ACPI_MSG_ERROR "ACPI Error: " -#define ACPI_MSG_EXCEPTION "ACPI Exception: " -#define ACPI_MSG_WARNING "ACPI Warning: " -#define ACPI_MSG_INFO "ACPI: " -#define ACPI_MSG_BIOS_ERROR "ACPI BIOS Error (bug): " -#define ACPI_MSG_BIOS_WARNING "ACPI BIOS Warning (bug): " -/* - * Common message suffix - */ -#define ACPI_MSG_SUFFIX \ - acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) /******************************************************************************* * * FUNCTION: acpi_error @@ -285,243 +248,3 @@ acpi_bios_warning(const char *module_name, } ACPI_EXPORT_SYMBOL(acpi_bios_warning) - -/* - * The remainder of this module contains internal error functions that may - * be configured out. - */ -#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP) -/******************************************************************************* - * - * FUNCTION: acpi_ut_predefined_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 - * node_flags - From Namespace node for the method/object - * format - Printf format string + additional args - * - * RETURN: None - * - * DESCRIPTION: Warnings for the predefined validation module. Messages are - * only emitted the first time a problem with a particular - * method/object is detected. This prevents a flood of error - * messages for methods that are repeatedly evaluated. - * - ******************************************************************************/ -void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_warning(const char *module_name, - u32 line_number, - char *pathname, - u8 node_flags, const char *format, ...) -{ - va_list arg_list; - - /* - * Warning messages for this method/object will be disabled after the - * first time a validation fails or an object is successfully repaired. - */ - if (node_flags & ANOBJ_EVALUATED) { - return; - } - - acpi_os_printf(ACPI_MSG_WARNING "%s: ", pathname); - - va_start(arg_list, format); - acpi_os_vprintf(format, arg_list); - ACPI_MSG_SUFFIX; - va_end(arg_list); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_predefined_info - * - * 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 - * node_flags - From Namespace node for the method/object - * format - Printf format string + additional args - * - * RETURN: None - * - * DESCRIPTION: Info messages for the predefined validation module. Messages - * are only emitted the first time a problem with a particular - * method/object is detected. This prevents a flood of - * messages for methods that are repeatedly evaluated. - * - ******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_info(const char *module_name, - u32 line_number, - char *pathname, u8 node_flags, const char *format, ...) -{ - va_list arg_list; - - /* - * Warning messages for this method/object will be disabled after the - * first time a validation fails or an object is successfully repaired. - */ - if (node_flags & ANOBJ_EVALUATED) { - return; - } - - acpi_os_printf(ACPI_MSG_INFO "%s: ", pathname); - - va_start(arg_list, format); - acpi_os_vprintf(format, arg_list); - ACPI_MSG_SUFFIX; - va_end(arg_list); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_predefined_bios_error - * - * 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 - * node_flags - From Namespace node for the method/object - * format - Printf format string + additional args - * - * RETURN: None - * - * DESCRIPTION: BIOS error message for predefined names. Messages - * are only emitted the first time a problem with a particular - * method/object is detected. This prevents a flood of - * messages for methods that are repeatedly evaluated. - * - ******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_bios_error(const char *module_name, - u32 line_number, - char *pathname, - u8 node_flags, const char *format, ...) -{ - va_list arg_list; - - /* - * Warning messages for this method/object will be disabled after the - * first time a validation fails or an object is successfully repaired. - */ - if (node_flags & ANOBJ_EVALUATED) { - return; - } - - acpi_os_printf(ACPI_MSG_BIOS_ERROR "%s: ", pathname); - - va_start(arg_list, format); - acpi_os_vprintf(format, arg_list); - ACPI_MSG_SUFFIX; - va_end(arg_list); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_namespace_error - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * internal_name - Name or path of the namespace node - * lookup_status - Exception code from NS lookup - * - * RETURN: None - * - * DESCRIPTION: Print error message with the full pathname for the NS node. - * - ******************************************************************************/ - -void -acpi_ut_namespace_error(const char *module_name, - u32 line_number, - const char *internal_name, acpi_status lookup_status) -{ - acpi_status status; - u32 bad_name; - char *name = NULL; - - ACPI_MSG_REDIRECT_BEGIN; - acpi_os_printf(ACPI_MSG_ERROR); - - if (lookup_status == AE_BAD_CHARACTER) { - - /* There is a non-ascii character in the name */ - - ACPI_MOVE_32_TO_32(&bad_name, - ACPI_CAST_PTR(u32, internal_name)); - acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name); - } else { - /* Convert path to external format */ - - status = acpi_ns_externalize_name(ACPI_UINT32_MAX, - internal_name, NULL, &name); - - /* Print target name */ - - if (ACPI_SUCCESS(status)) { - acpi_os_printf("[%s]", name); - } else { - acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); - } - - if (name) { - ACPI_FREE(name); - } - } - - acpi_os_printf(" Namespace lookup failure, %s", - acpi_format_exception(lookup_status)); - - ACPI_MSG_SUFFIX; - ACPI_MSG_REDIRECT_END; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_method_error - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * message - Error message to use on failure - * prefix_node - Prefix relative to the path - * path - Path to the node (optional) - * method_status - Execution status - * - * RETURN: None - * - * DESCRIPTION: Print error message with the full pathname for the method. - * - ******************************************************************************/ - -void -acpi_ut_method_error(const char *module_name, - u32 line_number, - const char *message, - struct acpi_namespace_node *prefix_node, - const char *path, acpi_status method_status) -{ - acpi_status status; - struct acpi_namespace_node *node = prefix_node; - - ACPI_MSG_REDIRECT_BEGIN; - acpi_os_printf(ACPI_MSG_ERROR); - - if (path) { - status = - acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, - &node); - if (ACPI_FAILURE(status)) { - acpi_os_printf("[Could not get node by pathname]"); - } - } - - acpi_ns_print_node_pathname(node, message); - acpi_os_printf(", %s", acpi_format_exception(method_status)); - - ACPI_MSG_SUFFIX; - ACPI_MSG_REDIRECT_END; -} - -#endif /* ACPI_NO_ERROR_MESSAGES */ -- cgit v1.2.3-70-g09d2 From 1d1ea1b723d9f239f736b8cf284327cbbf9d15d1 Mon Sep 17 00:00:00 2001 From: Chao Guan Date: Sat, 8 Jun 2013 00:58:14 +0000 Subject: ACPICA: Standardize all switch() blocks After many years, different formatting for switch() has crept in. This change makes every switch block identical. Chao Guan. ACPICA bugzilla 997. References: https://bugs.acpica.org/show_bug.cgi?id=997 Signed-off-by: Chao Guan Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/dscontrol.c | 4 ++-- drivers/acpi/acpica/dsfield.c | 4 ++++ drivers/acpi/acpica/dsinit.c | 1 + drivers/acpi/acpica/dsmthdat.c | 2 +- drivers/acpi/acpica/dsobject.c | 3 +-- drivers/acpi/acpica/dsopcode.c | 1 + drivers/acpi/acpica/dsutils.c | 5 ++--- drivers/acpi/acpica/dswexec.c | 3 +-- drivers/acpi/acpica/dswload.c | 7 ++++--- drivers/acpi/acpica/dswload2.c | 4 ++++ drivers/acpi/acpica/evgpe.c | 6 ++---- drivers/acpi/acpica/evgpeinit.c | 3 +++ drivers/acpi/acpica/evhandler.c | 7 +++++++ drivers/acpi/acpica/evmisc.c | 1 + drivers/acpi/acpica/evrgnini.c | 2 ++ drivers/acpi/acpica/evxfgpe.c | 3 +++ drivers/acpi/acpica/evxfregn.c | 1 + drivers/acpi/acpica/exconfig.c | 1 + drivers/acpi/acpica/exconvrt.c | 13 ++++++++++--- drivers/acpi/acpica/excreate.c | 3 --- drivers/acpi/acpica/exdebug.c | 2 ++ drivers/acpi/acpica/exdump.c | 2 ++ drivers/acpi/acpica/exfield.c | 4 ++++ drivers/acpi/acpica/exfldio.c | 2 -- drivers/acpi/acpica/exmisc.c | 12 +++++++++++- drivers/acpi/acpica/exoparg1.c | 16 ++++++++-------- drivers/acpi/acpica/exoparg2.c | 1 - drivers/acpi/acpica/exoparg3.c | 1 - drivers/acpi/acpica/exoparg6.c | 5 ----- drivers/acpi/acpica/exprep.c | 7 +++++++ drivers/acpi/acpica/exregion.c | 27 +++++++++++++++++++++++---- drivers/acpi/acpica/exresnte.c | 1 + drivers/acpi/acpica/exresolv.c | 6 +++++- drivers/acpi/acpica/exresop.c | 9 +++++---- drivers/acpi/acpica/exstore.c | 4 +--- drivers/acpi/acpica/exstoren.c | 4 ---- drivers/acpi/acpica/hwacpi.c | 2 +- drivers/acpi/acpica/hwgpe.c | 3 +++ drivers/acpi/acpica/hwregs.c | 4 ++-- drivers/acpi/acpica/hwxface.c | 3 +++ drivers/acpi/acpica/hwxfsleep.c | 4 ++++ drivers/acpi/acpica/nsaccess.c | 1 + drivers/acpi/acpica/nsconvert.c | 3 +++ drivers/acpi/acpica/nsdump.c | 10 ++++++++++ drivers/acpi/acpica/nsinit.c | 9 +++++++++ drivers/acpi/acpica/nspredef.c | 6 ++++++ drivers/acpi/acpica/nsprepkg.c | 5 ----- drivers/acpi/acpica/nsrepair.c | 1 + drivers/acpi/acpica/nsrepair2.c | 1 + drivers/acpi/acpica/nsutils.c | 3 +++ drivers/acpi/acpica/nsxfeval.c | 1 + drivers/acpi/acpica/psargs.c | 4 ++++ drivers/acpi/acpica/psloop.c | 2 +- drivers/acpi/acpica/psobject.c | 1 + drivers/acpi/acpica/psparse.c | 3 +-- drivers/acpi/acpica/pstree.c | 2 ++ drivers/acpi/acpica/rscalc.c | 2 ++ drivers/acpi/acpica/rsdump.c | 10 ++++++++++ drivers/acpi/acpica/rsmisc.c | 3 ++- drivers/acpi/acpica/rsutils.c | 5 +++++ drivers/acpi/acpica/rsxface.c | 1 + drivers/acpi/acpica/tbinstal.c | 4 ++++ drivers/acpi/acpica/utcopy.c | 11 +++++++---- drivers/acpi/acpica/utdelete.c | 3 ++- drivers/acpi/acpica/uteval.c | 5 +++++ drivers/acpi/acpica/utexcep.c | 1 + drivers/acpi/acpica/utids.c | 3 +++ drivers/acpi/acpica/utmisc.c | 2 ++ drivers/acpi/acpica/utobject.c | 5 ++--- drivers/acpi/acpica/utstring.c | 11 +++++++++++ drivers/acpi/acpica/uttrack.c | 8 ++++++++ 71 files changed, 242 insertions(+), 77 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index 7ea0f162f11..eb56b66444b 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -78,7 +78,6 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, switch (op->common.aml_opcode) { case AML_WHILE_OP: - /* * If this is an additional iteration of a while loop, continue. * There is no need to allocate a new control state. @@ -99,7 +98,6 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, /*lint -fallthrough */ case AML_IF_OP: - /* * IF/WHILE: Create a new control state to manage these * constructs. We need to manage these as a stack, in order @@ -142,6 +140,7 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, break; default: + break; } @@ -344,6 +343,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, case AML_NOOP_OP: /* Just do nothing! */ + break; case AML_BREAK_POINT_OP: diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index feadeed1012..d4bfe7b7f90 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -563,21 +563,25 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, */ switch (walk_state->opcode) { case AML_FIELD_OP: + arg = acpi_ps_get_arg(op, 2); type = ACPI_TYPE_LOCAL_REGION_FIELD; break; case AML_BANK_FIELD_OP: + arg = acpi_ps_get_arg(op, 4); type = ACPI_TYPE_LOCAL_BANK_FIELD; break; case AML_INDEX_FIELD_OP: + arg = acpi_ps_get_arg(op, 3); type = ACPI_TYPE_LOCAL_INDEX_FIELD; break; default: + return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index bc8e63f7784..14424200d24 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -127,6 +127,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, break; default: + break; } diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 3da80460ce3..c4b0b365723 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -285,6 +285,7 @@ acpi_ds_method_data_get_node(u8 type, break; default: + ACPI_ERROR((AE_INFO, "Type %u is invalid", type)); return_ACPI_STATUS(AE_TYPE); } @@ -428,7 +429,6 @@ acpi_ds_method_data_get_value(u8 type, return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); case ACPI_REFCLASS_LOCAL: - /* * No error message for this case, will be trapped again later to * detect and ignore cases of Store(local_x,local_x) diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index e20e9f84eee..63f0d220ca3 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -648,7 +648,6 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: - /* * Defer evaluation of Buffer term_arg operand */ @@ -660,7 +659,6 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, break; case ACPI_TYPE_PACKAGE: - /* * Defer evaluation of Package term_arg operand */ @@ -741,6 +739,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, break; default: + ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X", op_info->type)); status = AE_AML_OPERAND_TYPE; diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index ee6367b8eaf..1fc1ff114f2 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -636,6 +636,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, break; default: + return_ACPI_STATUS(AE_AML_BAD_OPCODE); } diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 99778997c35..c666fc01498 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -240,7 +240,6 @@ acpi_ds_is_result_used(union acpi_parse_object * op, case AML_IF_OP: case AML_WHILE_OP: - /* * If we are executing the predicate AND this is the predicate op, * we will use the return value @@ -254,7 +253,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, break; default: + /* Ignore other control opcodes */ + break; } @@ -263,7 +264,6 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_not_used; case AML_CLASS_CREATE: - /* * These opcodes allow term_arg(s) as operands and therefore * the operands can be method calls. The result is used. @@ -292,7 +292,6 @@ acpi_ds_is_result_used(union acpi_parse_object * op, goto result_not_used; default: - /* * In all other cases. the parent will actually use the return * object, so keep it. diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index e2199a94747..151d924817e 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -327,6 +327,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, break; default: + break; } @@ -488,7 +489,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) break; case AML_TYPE_METHOD_CALL: - /* * If the method is referenced from within a package * declaration, it is not a invocation of the method, just @@ -582,7 +582,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) switch (op->common.parent->common.aml_opcode) { case AML_NAME_OP: - /* * Put the Node on the object stack (Contains the ACPI Name * of this object) diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 6e17c0e24e6..95e681a36f9 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -74,6 +74,7 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) switch (pass_number) { case 1: + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_load1_begin_op; @@ -81,6 +82,7 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) break; case 2: + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_load2_begin_op; @@ -88,6 +90,7 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) break; case 3: + #ifndef ACPI_NO_METHOD_EXECUTION walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE; @@ -97,6 +100,7 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) break; default: + return (AE_BAD_PARAMETER); } @@ -161,7 +165,6 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, switch (walk_state->opcode) { case AML_SCOPE_OP: - /* * The target name of the Scope() operator must exist at this point so * that we can actually open the scope to enter new names underneath it. @@ -210,7 +213,6 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: - /* * These types we will allow, but we will change the type. * This enables some existing code of the form: @@ -232,7 +234,6 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, break; case ACPI_TYPE_METHOD: - /* * Allow scope change to root during execution of module-level * code. Root is typed METHOD during this time. diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index 4407ff2377d..b1f8f4725c2 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -509,6 +509,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; default: + /* All NAMED_FIELD opcodes must be handled above */ break; } @@ -548,6 +549,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; default: + /* Unknown opcode */ status = AE_OK; @@ -674,6 +676,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) #endif /* ACPI_NO_METHOD_EXECUTION */ default: + /* All NAMED_COMPLEX opcodes must be handled above */ break; } @@ -721,6 +724,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) break; default: + break; } diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index ae50d6cc535..c8a1f7d5931 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -529,7 +529,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { case ACPI_GPE_DISPATCH_NOTIFY: - /* * Implicit notify. * Dispatch a DEVICE_WAKE notify to the appropriate handler. @@ -582,7 +581,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) break; default: - return_VOID; /* Should never happen */ + + return_VOID; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ @@ -754,7 +754,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, case ACPI_GPE_DISPATCH_METHOD: case ACPI_GPE_DISPATCH_NOTIFY: - /* * Execute the method associated with the GPE * NOTE: Level-triggered GPEs are cleared after the method completes. @@ -770,7 +769,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, break; default: - /* * No handler or method to run! * 03/2010: This case should no longer be possible. We will not allow diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 72b8f6b3f4c..9037f17c960 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -363,14 +363,17 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, */ switch (name[1]) { case 'L': + type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': + type = ACPI_GPE_EDGE_TRIGGERED; break; default: + /* Unknown method type, just ignore it */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index d4f83112c2e..068af96134b 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -354,36 +354,43 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, 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; } diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index c986b2336b8..db59fe3f639 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -78,6 +78,7 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) return (TRUE); default: + return (FALSE); } } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 3bb616794b3..8354c4f7f10 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -596,7 +596,9 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, break; default: + /* Ignore other objects */ + break; } diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index aff4cc26121..7662f1a42ff 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -366,16 +366,19 @@ acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) switch (action) { case ACPI_GPE_ENABLE: + ACPI_SET_BIT(gpe_register_info->enable_for_wake, (u8)register_bit); break; case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, (u8)register_bit); break; default: + ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); status = AE_BAD_PARAMETER; break; diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 96c9e5f355a..80cecf83859 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -139,6 +139,7 @@ acpi_install_address_space_handler(acpi_handle device, break; default: + break; } diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index a689aacae2b..06d216c8d43 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -480,6 +480,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, break; default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index d2b9613bbf0..69e4a8cc9b7 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -99,6 +99,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, break; default: + return_ACPI_STATUS(AE_TYPE); } @@ -117,7 +118,6 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, switch (obj_desc->common.type) { case ACPI_TYPE_STRING: - /* * Convert string to an integer - for most cases, the string must be * hexadecimal as per the ACPI specification. The only exception (as @@ -161,6 +161,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, default: /* No other types can get here */ + break; } @@ -213,7 +214,6 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_OK); case ACPI_TYPE_INTEGER: - /* * Create a new Buffer object. * Need enough space for one integer @@ -233,7 +233,6 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, break; case ACPI_TYPE_STRING: - /* * Create a new Buffer object * Size will be the string length @@ -258,6 +257,7 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, break; default: + return_ACPI_STATUS(AE_TYPE); } @@ -304,15 +304,18 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width) switch (data_width) { case 1: + decimal_length = ACPI_MAX8_DECIMAL_DIGITS; break; case 4: + decimal_length = ACPI_MAX32_DECIMAL_DIGITS; break; case 8: default: + decimal_length = ACPI_MAX64_DECIMAL_DIGITS; break; } @@ -546,6 +549,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, break; default: + return_ACPI_STATUS(AE_TYPE); } @@ -599,6 +603,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: + /* No conversion allowed for these types */ if (destination_type != source_desc->common.type) { @@ -649,6 +654,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: + ACPI_ERROR((AE_INFO, "Bad destination type during conversion: 0x%X", destination_type)); @@ -664,6 +670,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; default: + ACPI_ERROR((AE_INFO, "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", GET_CURRENT_ARG_TYPE(walk_state->op_info-> diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index 26a13f67977..269e81d86ef 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -103,7 +103,6 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_BUFFER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_BUFFER_FIELD: - /* * These types open a new scope, so we need the NS node in order to access * any children. @@ -113,7 +112,6 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: case ACPI_TYPE_LOCAL_SCOPE: - /* * The new alias has the type ALIAS and points to the original * NS node, not the object itself. @@ -124,7 +122,6 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_METHOD: - /* * Control method aliases need to be differentiated */ diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index 7eb853cd279..81c72a4ecd8 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -193,6 +193,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, return_VOID; default: + break; } @@ -226,6 +227,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, break; default: + acpi_ex_do_debug_object((source_desc-> reference. node)->object, diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index e5a3c249f7f..c740f24e310 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -357,6 +357,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, switch (info->opcode) { case ACPI_EXD_INIT: + break; case ACPI_EXD_TYPE: @@ -718,6 +719,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) break; default: + /* Unknown Type */ acpi_os_printf("Unknown Type %X\n", obj_desc->common.type); diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 7d4bae71e8c..c2a65aaf29a 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -331,21 +331,25 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: + buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); break; case ACPI_TYPE_BUFFER: + buffer = source_desc->buffer.pointer; length = source_desc->buffer.length; break; case ACPI_TYPE_STRING: + buffer = source_desc->string.pointer; length = source_desc->string.length; break; default: + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index c84ee956fa4..7e0afe72487 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -446,7 +446,6 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, break; case ACPI_TYPE_LOCAL_BANK_FIELD: - /* * Ensure that the bank_value is not beyond the capacity of * the register @@ -488,7 +487,6 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, break; case ACPI_TYPE_LOCAL_INDEX_FIELD: - /* * Ensure that the index_value is not beyond the capacity of * the register diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 72a2a13b6d3..00bf2987757 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -105,7 +105,6 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, break; case ACPI_DESC_TYPE_NAMED: - /* * A named reference that has already been resolved to a Node */ @@ -261,20 +260,24 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, */ switch (operand0->common.type) { case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); break; case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); break; default: + ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", operand0->common.type)); status = AE_AML_INTERNAL; @@ -519,6 +522,7 @@ acpi_ex_do_logical_numeric_op(u16 opcode, break; default: + status = AE_AML_INTERNAL; break; } @@ -580,20 +584,24 @@ acpi_ex_do_logical_op(u16 opcode, */ switch (operand0->common.type) { case ACPI_TYPE_INTEGER: + status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); break; case ACPI_TYPE_STRING: + status = acpi_ex_convert_to_string(operand1, &local_operand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: + status = acpi_ex_convert_to_buffer(operand1, &local_operand1); break; default: + status = AE_AML_INTERNAL; break; } @@ -636,6 +644,7 @@ acpi_ex_do_logical_op(u16 opcode, break; default: + status = AE_AML_INTERNAL; break; } @@ -703,6 +712,7 @@ acpi_ex_do_logical_op(u16 opcode, break; default: + status = AE_AML_INTERNAL; break; } diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index b60c877f590..814b4a3d656 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -327,7 +327,6 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) break; case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ - /* * The 64-bit ACPI integer can hold 16 4-bit BCD characters * (if table is 32-bit, integer can hold 8 BCD characters) @@ -407,7 +406,6 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) break; case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */ - /* * This op is a little strange because the internal return value is * different than the return value stored in the result descriptor @@ -442,13 +440,14 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) goto cleanup; default: + /* No other opcodes get here */ + break; } break; case AML_STORE_OP: /* Store (Source, Target) */ - /* * A store operand is typically a number, string, buffer or lvalue * Be careful about deleting the source object, @@ -615,7 +614,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) case AML_DECREMENT_OP: /* Decrement (Operand) */ case AML_INCREMENT_OP: /* Increment (Operand) */ - /* * Create a new integer. Can't just get the base integer and * increment it because it may be an Arg or Field. @@ -682,7 +680,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case AML_TYPE_OP: /* object_type (source_object) */ - /* * 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 @@ -709,7 +706,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case AML_SIZE_OF_OP: /* size_of (source_object) */ - /* * Note: The operand is not resolved at this point because we want to * get the associated object, not its value. @@ -735,10 +731,12 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ switch (type) { case ACPI_TYPE_INTEGER: + value = acpi_gbl_integer_byte_width; break; case ACPI_TYPE_STRING: + value = temp_desc->string.length; break; @@ -759,6 +757,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; default: + ACPI_ERROR((AE_INFO, "Operand must be Buffer/Integer/String/Package - found type %s", acpi_ut_get_type_name(type))); @@ -860,9 +859,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_STRING: + break; default: + status = AE_AML_OPERAND_TYPE; goto cleanup; } @@ -923,7 +924,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ switch (operand[0]->reference.class) { case ACPI_REFCLASS_INDEX: - /* * The target type for the Index operator must be * either a Buffer or a Package @@ -956,7 +956,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; case ACPI_TYPE_PACKAGE: - /* * Return the referenced element of the package. We must * add another reference to the referenced object, however. @@ -999,6 +998,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) break; default: + ACPI_ERROR((AE_INFO, "Unknown class in reference(%p) - 0x%2.2X", operand[0], diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index b0838a4ea53..d5088f7030c 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -304,7 +304,6 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) break; case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */ - /* * Input object is guaranteed to be a buffer at this point (it may have * been converted.) Copy the raw buffer data to a new object of diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index 2d7491f3126..37656f12f20 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -155,7 +155,6 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) switch (walk_state->opcode) { case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ - /* * Create the return object. The Source operand is guaranteed to be * either a String or a Buffer, so just use its type. diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index b76b97002df..879b6cd8319 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -119,7 +119,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MEQ: - /* * True if equal: (P[i] == M) * Change to: (M == P[i]) @@ -133,7 +132,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MLE: - /* * True if less than or equal: (P[i] <= M) (P[i] not_greater than M) * Change to: (M >= P[i]) (M not_less than P[i]) @@ -148,7 +146,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MLT: - /* * True if less than: (P[i] < M) * Change to: (M > P[i]) @@ -162,7 +159,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MGE: - /* * True if greater than or equal: (P[i] >= M) (P[i] not_less than M) * Change to: (M <= P[i]) (M not_greater than P[i]) @@ -177,7 +173,6 @@ acpi_ex_do_match(u32 match_op, break; case MATCH_MGT: - /* * True if greater than: (P[i] > M) * Change to: (M < P[i]) diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 6b728aef2dc..5a588611ab4 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -253,26 +253,31 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, case AML_FIELD_ACCESS_BYTE: case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ + byte_alignment = 1; bit_length = 8; break; case AML_FIELD_ACCESS_WORD: + byte_alignment = 2; bit_length = 16; break; case AML_FIELD_ACCESS_DWORD: + byte_alignment = 4; bit_length = 32; break; case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ + byte_alignment = 8; bit_length = 64; break; default: + /* Invalid field access type */ ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access)); @@ -598,7 +603,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) break; default: + /* No other types should get here */ + break; } diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 182abaf045e..303429bb4d5 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -88,22 +88,27 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: + length = 1; break; case 16: + length = 2; break; case 32: + length = 4; break; case 64: + length = 8; break; default: + ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u", bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); @@ -214,23 +219,29 @@ acpi_ex_system_memory_space_handler(u32 function, *value = 0; switch (bit_width) { case 8: - *value = (u64) ACPI_GET8(logical_addr_ptr); + + *value = (u64)ACPI_GET8(logical_addr_ptr); break; case 16: - *value = (u64) ACPI_GET16(logical_addr_ptr); + + *value = (u64)ACPI_GET16(logical_addr_ptr); break; case 32: - *value = (u64) ACPI_GET32(logical_addr_ptr); + + *value = (u64)ACPI_GET32(logical_addr_ptr); break; case 64: - *value = (u64) ACPI_GET64(logical_addr_ptr); + + *value = (u64)ACPI_GET64(logical_addr_ptr); break; default: + /* bit_width was already validated */ + break; } break; @@ -239,28 +250,35 @@ acpi_ex_system_memory_space_handler(u32 function, switch (bit_width) { case 8: + ACPI_SET8(logical_addr_ptr, *value); break; case 16: + ACPI_SET16(logical_addr_ptr, *value); break; case 32: + ACPI_SET32(logical_addr_ptr, *value); break; case 64: + ACPI_SET64(logical_addr_ptr, *value); break; default: + /* bit_width was already validated */ + break; } break; default: + status = AE_BAD_PARAMETER; break; } @@ -320,6 +338,7 @@ acpi_ex_system_io_space_handler(u32 function, break; default: + status = AE_BAD_PARAMETER; break; } diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index 8565b6bd12b..acd34f59931 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -248,6 +248,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, break; default: + /* No named references are allowed here */ ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index e4f9dfbb2a1..ac04278ad28 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -156,7 +156,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, switch (ref_type) { case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_ARG: - /* * Get the local from the method's state info * Note: this increments the local's object reference count @@ -309,6 +308,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, break; default: + break; } @@ -348,10 +348,12 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { case ACPI_DESC_TYPE_OPERAND: + type = obj_desc->common.type; break; case ACPI_DESC_TYPE_NAMED: + type = ((struct acpi_namespace_node *)obj_desc)->type; obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) @@ -538,7 +540,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, break; default: + /* No change to Type required */ + break; } diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 9fb9f5e9a4d..00e5af7129c 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -307,7 +307,6 @@ acpi_ex_resolve_operands(u16 opcode, case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ case ARGI_SIMPLE_TARGET: /* Name, Local, or arg - no implicit conversion */ - /* * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE * A Namespace Node is OK as-is @@ -326,7 +325,6 @@ acpi_ex_resolve_operands(u16 opcode, goto next_operand; case ARGI_DATAREFOBJ: /* Store operator only */ - /* * We don't want to resolve index_op reference objects during * a store because this would be an implicit de_ref_of operation. @@ -343,7 +341,9 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + /* All cases covered above */ + break; } @@ -433,7 +433,6 @@ acpi_ex_resolve_operands(u16 opcode, goto next_operand; case ARGI_BUFFER: - /* * Need an operand of type ACPI_TYPE_BUFFER, * But we can implicitly convert from a STRING or INTEGER @@ -459,7 +458,6 @@ acpi_ex_resolve_operands(u16 opcode, goto next_operand; case ARGI_STRING: - /* * Need an operand of type ACPI_TYPE_STRING, * But we can implicitly convert from a BUFFER or INTEGER @@ -562,6 +560,7 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + ACPI_ERROR((AE_INFO, "Needed [Buffer/String/Package/Reference], found [%s] %p", acpi_ut_get_object_type_name @@ -584,6 +583,7 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + ACPI_ERROR((AE_INFO, "Needed [Buffer/String/Package], found [%s] %p", acpi_ut_get_object_type_name @@ -605,6 +605,7 @@ acpi_ex_resolve_operands(u16 opcode, break; default: + ACPI_ERROR((AE_INFO, "Needed [Region/Buffer], found [%s] %p", acpi_ut_get_object_type_name diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index 93c6049c2d7..2bdba6f7d76 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -114,6 +114,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, switch (dest_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: + break; case ACPI_TYPE_INTEGER: @@ -178,7 +179,6 @@ acpi_ex_store(union acpi_operand_object *source_desc, break; case ACPI_REFCLASS_DEBUG: - /* * Storing to the Debug object causes the value stored to be * displayed and otherwise has no effect -- see ACPI Specification @@ -291,7 +291,6 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, break; case ACPI_TYPE_BUFFER_FIELD: - /* * Store into a Buffer or String (not actually a real buffer_field) * at a location defined by an Index. @@ -447,7 +446,6 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: - /* * These target types are all of type Integer/String/Buffer, and * therefore support implicit conversion before the store. diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index 1cefe777068..20d809d90c5 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -85,11 +85,9 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * These cases all require only Integers or values that * can be converted to Integers (Strings or Buffers) */ - case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: - /* * Stores into a Field/Region or into a Integer/Buffer/String * are all essentially the same. This case handles the @@ -133,7 +131,6 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: - /* * All aliases should have been resolved earlier, during the * operand resolution phase. @@ -144,7 +141,6 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, case ACPI_TYPE_PACKAGE: default: - /* * All other types than Alias and the various Fields come here, * including the untyped case - ACPI_TYPE_ANY. diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index 579c3a53ac8..3d36df828f5 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -108,7 +108,6 @@ acpi_status acpi_hw_set_mode(u32 mode) break; case ACPI_SYS_MODE_LEGACY: - /* * BIOS should clear all fixed status bits and restore fixed event * enable bits to default @@ -120,6 +119,7 @@ acpi_status acpi_hw_set_mode(u32 mode) break; default: + return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 20d02e93c99..96540506058 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -127,14 +127,17 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) /*lint -fallthrough */ case ACPI_GPE_ENABLE: + ACPI_SET_BIT(enable_mask, register_bit); break; case ACPI_GPE_DISABLE: + ACPI_CLEAR_BIT(enable_mask, register_bit); break; default: + ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action)); return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 083d6551f0e..8d2e866be15 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -419,6 +419,7 @@ acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) break; default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id)); status = AE_BAD_PARAMETER; break; @@ -491,7 +492,6 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ - /* * Perform a read first to preserve certain bits (per ACPI spec) * Note: This includes SCI_EN, we never want to change this bit @@ -520,7 +520,6 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - /* * For control registers, all reserved bits must be preserved, * as per the ACPI spec. @@ -555,6 +554,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id)); status = AE_BAD_PARAMETER; break; diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index f4224e6f4e7..5ee7a814cd9 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -528,10 +528,12 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) 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; @@ -545,6 +547,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) case 2: default: + if ((elements[0]->common.type != ACPI_TYPE_INTEGER) || (elements[1]->common.type != ACPI_TYPE_INTEGER)) { status = AE_AML_OPERAND_TYPE; diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 35eebdac0f9..111849c2117 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -314,20 +314,24 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) switch (sleep_state) { case ACPI_STATE_S0: + sst_value = ACPI_SST_WORKING; break; case ACPI_STATE_S1: case ACPI_STATE_S2: case ACPI_STATE_S3: + sst_value = ACPI_SST_SLEEPING; break; case ACPI_STATE_S4: + sst_value = ACPI_SST_SLEEP_CONTEXT; break; default: + sst_value = ACPI_SST_INDICATOR_OFF; /* Default is off */ break; } diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 8769cf83b04..c5316e5bd4a 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -151,6 +151,7 @@ acpi_status acpi_ns_root_initialize(void) */ switch (init_val->type) { case ACPI_TYPE_METHOD: + obj_desc->method.param_count = (u8) ACPI_TO_INTEGER(val); obj_desc->common.flags |= AOPOBJ_DATA_VALID; diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index 8f79a9d2d50..acd2964c269 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -103,6 +103,7 @@ acpi_ns_convert_to_integer(union acpi_operand_object *original_object, break; default: + return (AE_AML_OPERAND_TYPE); } @@ -191,6 +192,7 @@ acpi_ns_convert_to_string(union acpi_operand_object *original_object, break; default: + return (AE_AML_OPERAND_TYPE); } @@ -294,6 +296,7 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, break; default: + return (AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index ce6e9732620..7418c77fde8 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -244,10 +244,12 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: case ACPI_TYPE_METHOD: + acpi_os_printf(""); break; default: + break; } @@ -433,6 +435,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, break; default: + break; } break; @@ -567,32 +570,39 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, goto cleanup; case ACPI_TYPE_BUFFER_FIELD: + obj_desc = (union acpi_operand_object *)obj_desc->buffer_field. buffer_obj; break; case ACPI_TYPE_PACKAGE: + obj_desc = (void *)obj_desc->package.elements; break; case ACPI_TYPE_METHOD: + obj_desc = (void *)obj_desc->method.aml_start; break; case ACPI_TYPE_LOCAL_REGION_FIELD: + obj_desc = (void *)obj_desc->field.region_obj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: + obj_desc = (void *)obj_desc->bank_field.region_obj; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: + obj_desc = (void *)obj_desc->index_field.index_obj; break; default: + goto cleanup; } diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 23e426f7fd1..dd2ceae3f71 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -266,28 +266,34 @@ acpi_ns_init_one_object(acpi_handle obj_handle, switch (type) { case ACPI_TYPE_REGION: + info->op_region_count++; break; case ACPI_TYPE_BUFFER_FIELD: + info->field_count++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: + info->field_count++; break; case ACPI_TYPE_BUFFER: + info->buffer_count++; break; case ACPI_TYPE_PACKAGE: + info->package_count++; break; default: /* No init required, just exit now */ + return (AE_OK); } @@ -337,7 +343,9 @@ acpi_ns_init_one_object(acpi_handle obj_handle, break; default: + /* No other types can get here */ + break; } @@ -416,6 +424,7 @@ acpi_ns_find_ini_methods(acpi_handle obj_handle, break; default: + break; } diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 5c83a8b1c15..600268d33aa 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -344,26 +344,32 @@ static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object) switch (return_object->common.type) { case ACPI_TYPE_INTEGER: + return_btype = ACPI_RTYPE_INTEGER; break; case ACPI_TYPE_BUFFER: + return_btype = ACPI_RTYPE_BUFFER; break; case ACPI_TYPE_STRING: + return_btype = ACPI_RTYPE_STRING; break; case ACPI_TYPE_PACKAGE: + return_btype = ACPI_RTYPE_PACKAGE; break; case ACPI_TYPE_LOCAL_REFERENCE: + return_btype = ACPI_RTYPE_REFERENCE; break; default: + /* Not one of the supported objects, must be incorrect */ return_btype = ACPI_RTYPE_ANY; diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index ab2a3f477e1..6d55cef7916 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -136,7 +136,6 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, */ switch (package->ret_info.type) { case ACPI_PTYPE1_FIXED: - /* * The package count is fixed and there are no sub-packages * @@ -169,7 +168,6 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, break; case ACPI_PTYPE1_VAR: - /* * The package count is variable, there are no sub-packages, and all * elements must be of the same type @@ -186,7 +184,6 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, 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 @@ -284,7 +281,6 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, 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. @@ -500,7 +496,6 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, break; case ACPI_PTYPE2_COUNT: - /* * First element is the (Integer) count of elements, including * the count field (the ACPI name is num_elements) diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 89caef04691..f8e71ea6031 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -480,6 +480,7 @@ acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, case ACPI_PTYPE2_MIN: case ACPI_PTYPE2_REV_FIXED: case ACPI_PTYPE2_FIX_VAR: + break; default: diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 39acc4e6b38..daac8daeaa9 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -320,6 +320,7 @@ acpi_ns_repair_FDE(struct acpi_evaluate_info *info, break; default: + return (AE_AML_OPERAND_TYPE); } diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 2808586fad3..08c0b5beec8 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -419,10 +419,12 @@ acpi_ns_externalize_name(u32 internal_name_length, switch (internal_name[0]) { case AML_ROOT_PREFIX: + prefix_length = 1; break; case AML_PARENT_PREFIX: + for (i = 0; i < internal_name_length; i++) { if (ACPI_IS_PARENT_PREFIX(internal_name[i])) { prefix_length = i + 1; @@ -438,6 +440,7 @@ acpi_ns_externalize_name(u32 internal_name_length, break; default: + break; } diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 82bec40d450..f553cfdb71d 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -511,6 +511,7 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) break; default: + return; } diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 9f25a3d4e99..91a5a69db80 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -629,24 +629,28 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state switch (opcode) { case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + buffer_length = ACPI_GET8(parser_state->aml); parser_state->aml += 1; break; case AML_WORD_OP: /* AML_WORDDATA_ARG */ + buffer_length = ACPI_GET16(parser_state->aml); parser_state->aml += 2; break; case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + buffer_length = ACPI_GET32(parser_state->aml); parser_state->aml += 4; break; default: + buffer_length = 0; break; } diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 63c45544748..065b44ae538 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -164,7 +164,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, case AML_IF_OP: case AML_ELSE_OP: case AML_WHILE_OP: - /* * Currently supported module-level opcodes are: * IF/ELSE/WHILE. These appear to be the most common, @@ -289,6 +288,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, default: /* No action for all other opcodes */ + break; } diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c index 12c4028002b..95dc608a66a 100644 --- a/drivers/acpi/acpica/psobject.c +++ b/drivers/acpi/acpica/psobject.c @@ -402,6 +402,7 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, switch (status) { case AE_OK: + break; case AE_CTRL_TRANSFER: diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index abc4c48b2ed..86198a9139b 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -176,10 +176,10 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, switch (parent_info->class) { case AML_CLASS_CONTROL: + break; case AML_CLASS_CREATE: - /* * These opcodes contain term_arg operands. The current * op must be replaced by a placeholder return op @@ -192,7 +192,6 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, break; case AML_CLASS_NAMED_OBJECT: - /* * These opcodes contain term_arg operands. The current * op must be replaced by a placeholder return op diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index c1934bf04f0..877dc0de8df 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -308,7 +308,9 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) break; default: + /* All others have no children */ + break; } diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 72077fa1eea..608ebb56b67 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -352,6 +352,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) break; default: + break; } @@ -539,6 +540,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, break; default: + break; } diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index b5fc0db2e87..8a2d4986b0a 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -120,17 +120,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* Strings */ case ACPI_RSD_LITERAL: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table->pointer)); break; case ACPI_RSD_STRING: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, target)); break; /* Data items, 8/16/32/64 bit */ case ACPI_RSD_UINT8: + if (table->pointer) { acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> @@ -142,20 +145,24 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; case ACPI_RSD_UINT16: + acpi_rs_out_integer16(name, ACPI_GET16(target)); break; case ACPI_RSD_UINT32: + acpi_rs_out_integer32(name, ACPI_GET32(target)); break; case ACPI_RSD_UINT64: + acpi_rs_out_integer64(name, ACPI_GET64(target)); break; /* Flags: 1-bit and 2-bit flags supported */ case ACPI_RSD_1BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & @@ -163,6 +170,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; case ACPI_RSD_2BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & @@ -170,6 +178,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; case ACPI_RSD_3BITFLAG: + acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & @@ -258,6 +267,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) break; default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", table->opcode); return; diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index d5bf05a9609..80d12994e0d 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -194,7 +194,6 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, break; case ACPI_RSC_COUNT_GPIO_RES: - /* * Vendor data is optional (length/offset may both be zero) * Examine vendor data length field first @@ -410,12 +409,14 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, */ switch (info->resource_offset) { case ACPI_RSC_COMPARE_AML_LENGTH: + if (aml_resource_length != info->value) { goto exit; } break; case ACPI_RSC_COMPARE_VALUE: + if (ACPI_GET8(source) != info->value) { goto exit; } diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 59bdf37164b..480b6b40c5e 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -147,6 +147,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) case ACPI_RSC_MOVE_GPIO_RES: case ACPI_RSC_MOVE_SERIAL_VEN: case ACPI_RSC_MOVE_SERIAL_RES: + ACPI_MEMCPY(destination, source, item_count); return; @@ -157,21 +158,25 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) */ case ACPI_RSC_MOVE16: case ACPI_RSC_MOVE_GPIO_PIN: + ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], &ACPI_CAST_PTR(u16, source)[i]); break; case ACPI_RSC_MOVE32: + ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], &ACPI_CAST_PTR(u32, source)[i]); break; case ACPI_RSC_MOVE64: + ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], &ACPI_CAST_PTR(u64, source)[i]); break; default: + return; } } diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index c0e5d2d3ce6..94e3517554f 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -402,6 +402,7 @@ acpi_resource_to_address64(struct acpi_resource *resource, break; default: + return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index e57cd38004e..a04e54d984d 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -471,15 +471,19 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc) } switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { case ACPI_TABLE_ORIGIN_MAPPED: + acpi_os_unmap_memory(table_desc->pointer, table_desc->length); break; + case ACPI_TABLE_ORIGIN_ALLOCATED: + ACPI_FREE(table_desc->pointer); break; /* Not mapped or allocated, there is nothing we can do */ default: + return; } diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index e4c9291fc0a..1731c27c36a 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -178,7 +178,6 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, switch (internal_object->reference.class) { case ACPI_REFCLASS_NAME: - /* * For namepath, return the object handle ("reference") * We are referring to the namespace node @@ -264,7 +263,6 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, switch (object_type) { case ACPI_COPY_TYPE_SIMPLE: - /* * This is a simple or null object */ @@ -278,7 +276,6 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, break; case ACPI_COPY_TYPE_PACKAGE: - /* * Build the package object */ @@ -304,6 +301,7 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, break; default: + return (AE_BAD_PARAMETER); } @@ -481,6 +479,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, return_ACPI_STATUS(AE_OK); default: + /* All other types are not supported */ ACPI_ERROR((AE_INFO, @@ -544,7 +543,9 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, break; default: + /* Other types can't get here */ + break; } @@ -800,7 +801,9 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, break; default: + /* Nothing to do for other simple objects */ + break; } @@ -868,7 +871,6 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, break; case ACPI_COPY_TYPE_PACKAGE: - /* * This object is a package - go down another nesting level * Create and build the package object @@ -891,6 +893,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, break; default: + return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 29b930250b6..d6b33f29d32 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -303,6 +303,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) break; default: + break; } @@ -508,7 +509,6 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: - /* * Update the notify objects for these types (if present) * Two lists, system and device notify handlers. @@ -623,6 +623,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) case ACPI_TYPE_REGION: default: + break; /* No subobjects for all other types */ } diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 9d6802911c0..ee83adb97b1 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -123,22 +123,27 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, switch ((info->return_object)->common.type) { case ACPI_TYPE_INTEGER: + return_btype = ACPI_BTYPE_INTEGER; break; case ACPI_TYPE_BUFFER: + return_btype = ACPI_BTYPE_BUFFER; break; case ACPI_TYPE_STRING: + return_btype = ACPI_BTYPE_STRING; break; case ACPI_TYPE_PACKAGE: + return_btype = ACPI_BTYPE_PACKAGE; break; default: + return_btype = 0; break; } diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index b543a144941..ff6d9e8aa84 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -146,6 +146,7 @@ const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status status) break; default: + break; } diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index 43a170a74a6..fa69071db41 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -341,14 +341,17 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, switch (cid_objects[i]->common.type) { case ACPI_TYPE_INTEGER: + string_area_size += ACPI_EISAID_STRING_SIZE; break; case ACPI_TYPE_STRING: + string_area_size += cid_objects[i]->string.length + 1; break; default: + status = AE_TYPE; goto cleanup; } diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 785fdd07ae5..02f9101b65e 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -382,10 +382,12 @@ acpi_ut_display_init_pathname(u8 type, switch (type) { case ACPI_TYPE_METHOD: + acpi_os_printf("Executing "); break; default: + acpi_os_printf("Initializing "); break; } diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index 1099f5c069f..aa61f66ee86 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -129,6 +129,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char break; default: + /* All others have no secondary object */ break; } @@ -353,6 +354,7 @@ u8 acpi_ut_valid_internal_object(void *object) return (TRUE); default: + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p is not not an ACPI operand obj [%s]\n", object, acpi_ut_get_descriptor_name(object))); @@ -509,7 +511,6 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, switch (internal_object->reference.class) { case ACPI_REFCLASS_NAME: - /* * Get the actual length of the full pathname to this object. * The reference will be converted to the pathname to the object @@ -525,7 +526,6 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, break; default: - /* * No other reference opcodes are supported. * Notably, Locals and Args are not supported, but this may be @@ -585,7 +585,6 @@ acpi_ut_get_element_length(u8 object_type, switch (object_type) { case ACPI_COPY_TYPE_SIMPLE: - /* * Simple object - just get the size (Null object/entry is handled * here also) and sum it into the running package length diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index b3e36a81aa4..31a06a17e29 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -186,10 +186,13 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) switch (base) { case ACPI_ANY_BASE: case 16: + break; default: + /* Invalid Base */ + return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -355,36 +358,44 @@ void acpi_ut_print_string(char *string, u8 max_length) 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; diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 62774c7b76a..160f13f4aab 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -603,6 +603,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) { case ACPI_DESC_TYPE_OPERAND: + if (element->size == sizeof(union acpi_operand_object)) @@ -613,6 +614,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) break; case ACPI_DESC_TYPE_PARSER: + if (element->size == sizeof(union acpi_parse_object)) { @@ -622,6 +624,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) break; case ACPI_DESC_TYPE_NAMED: + if (element->size == sizeof(struct acpi_namespace_node)) @@ -632,6 +635,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) break; default: + break; } @@ -639,6 +643,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) switch (descriptor_type) { case ACPI_DESC_TYPE_OPERAND: + acpi_os_printf ("%12.12s RefCount 0x%04X\n", acpi_ut_get_type_name @@ -649,6 +654,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) break; case ACPI_DESC_TYPE_PARSER: + acpi_os_printf ("AmlOpcode 0x%04hX\n", descriptor->op.asl. @@ -656,6 +662,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) break; case ACPI_DESC_TYPE_NAMED: + acpi_os_printf("%4.4s\n", acpi_ut_get_node_name (&descriptor-> @@ -663,6 +670,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) break; default: + acpi_os_printf("\n"); break; } -- cgit v1.2.3-70-g09d2 From b75dd2977fc3c5848f739681fc799f27b1322e44 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Sat, 8 Jun 2013 00:58:48 +0000 Subject: ACPICA: Add option to disable loading of SSDTs from the RSDT/XSDT Optionally do not load any SSDTs from the RSDT/XSDT during initialization. This can be useful for overriding SSDTs using DSDT overriding, thus useful for debugging ACPI problems on some machines. Lv Zheng. ACPICA BZ 1005. References: https://bugs.acpica.org/show_bug.cgi?id=1005 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acglobal.h | 6 ++++++ drivers/acpi/acpica/tbxfload.c | 25 ++++++++++--------------- drivers/acpi/osl.c | 11 +++++++++++ include/acpi/acpixf.h | 1 + 4 files changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 07160928ca2..b8d38117a20 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -132,6 +132,12 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); */ u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_auto_repair, FALSE); +/* + * Optionally do not load any SSDTs from the RSDT/XSDT during initialization. + * This can be useful for debugging ACPI problems on some machines. + */ +u8 ACPI_INIT_GLOBAL(acpi_gbl_disable_ssdt_table_load, FALSE); + /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ struct acpi_table_fadt acpi_gbl_FADT; diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 67e046ec8f0..0ba9e328d5d 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -53,8 +53,6 @@ ACPI_MODULE_NAME("tbxfload") /* Local prototypes */ static acpi_status acpi_tb_load_namespace(void); -static int no_auto_ssdt; - /******************************************************************************* * * FUNCTION: acpi_load_tables @@ -180,8 +178,16 @@ static acpi_status acpi_tb_load_namespace(void) continue; } - if (no_auto_ssdt) { - printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n"); + /* + * Optionally do not load any SSDTs from the RSDT/XSDT. This can + * be useful for debugging ACPI problems on some machines. + */ + if (acpi_gbl_disable_ssdt_table_load) { + ACPI_INFO((AE_INFO, "Ignoring %4.4s at %p", + acpi_gbl_root_table_list.tables[i].signature. + ascii, ACPI_CAST_PTR(void, + acpi_gbl_root_table_list. + tables[i].address))); continue; } @@ -376,14 +382,3 @@ acpi_status acpi_unload_parent_table(acpi_handle object) } ACPI_EXPORT_SYMBOL(acpi_unload_parent_table) - -static int __init acpi_no_auto_ssdt_setup(char *s) { - - printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); - - no_auto_ssdt = 1; - - return 1; -} - -__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e72186340fe..da6b6634e5b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1715,6 +1715,17 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) } #endif +static int __init acpi_no_auto_ssdt_setup(char *s) +{ + printk(KERN_NOTICE PREFIX "SSDT auto-load disabled\n"); + + acpi_gbl_disable_ssdt_table_load = TRUE; + + return 1; +} + +__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); + acpi_status __init acpi_os_initialize(void) { acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block); diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 156126449bf..5d9bf46f2ab 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -80,6 +80,7 @@ extern bool acpi_gbl_enable_aml_debug_object; extern u8 acpi_gbl_copy_dsdt_locally; extern u8 acpi_gbl_truncate_io_addresses; extern u8 acpi_gbl_disable_auto_repair; +extern u8 acpi_gbl_disable_ssdt_table_load; /* * Hardware-reduced prototypes. All interfaces that use these macros will -- cgit v1.2.3-70-g09d2 From 42f47869c6a73a6893c998725365b587b0311f9a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 8 Jun 2013 00:59:02 +0000 Subject: ACPICA: Split table print utilities to a new a separate file Improves configurability of ACPICA. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + drivers/acpi/acpica/tbprint.c | 237 ++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpica/tbutils.c | 191 +--------------------------------- 3 files changed, 239 insertions(+), 190 deletions(-) create mode 100644 drivers/acpi/acpica/tbprint.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 987bf41ec90..438304086ff 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -138,6 +138,7 @@ acpi-y += \ tbfadt.o \ tbfind.o \ tbinstal.o \ + tbprint.o \ tbutils.o \ tbxface.o \ tbxfload.o \ diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c new file mode 100644 index 00000000000..dc963f823d2 --- /dev/null +++ b/drivers/acpi/acpica/tbprint.c @@ -0,0 +1,237 @@ +/****************************************************************************** + * + * Module Name: tbprint - Table output utilities + * + *****************************************************************************/ + +/* + * 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 +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbprint") + +/* Local prototypes */ +static void acpi_tb_fix_string(char *string, acpi_size length); + +static void +acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, + struct acpi_table_header *header); + +/******************************************************************************* + * + * FUNCTION: acpi_tb_fix_string + * + * PARAMETERS: string - String to be repaired + * length - Maximum length + * + * RETURN: None + * + * DESCRIPTION: Replace every non-printable or non-ascii byte in the string + * with a question mark '?'. + * + ******************************************************************************/ + +static void acpi_tb_fix_string(char *string, acpi_size length) +{ + + while (length && *string) { + if (!ACPI_IS_PRINT(*string)) { + *string = '?'; + } + string++; + length--; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_cleanup_table_header + * + * PARAMETERS: out_header - Where the cleaned header is returned + * header - Input ACPI table header + * + * RETURN: Returns the cleaned header in out_header + * + * DESCRIPTION: Copy the table header and ensure that all "string" fields in + * the header consist of printable characters. + * + ******************************************************************************/ + +static void +acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, + struct acpi_table_header *header) +{ + + ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); + + acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); + acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_print_table_header + * + * PARAMETERS: address - Table physical address + * header - Table header + * + * RETURN: None + * + * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. + * + ******************************************************************************/ + +void +acpi_tb_print_table_header(acpi_physical_address address, + struct acpi_table_header *header) +{ + struct acpi_table_header local_header; + + /* + * The reason that the Address is cast to a void pointer is so that we + * can use %p which will work properly on both 32-bit and 64-bit hosts. + */ + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { + + /* FACS only has signature and length fields */ + + ACPI_INFO((AE_INFO, "%4.4s %p %05X", + header->signature, ACPI_CAST_PTR(void, address), + header->length)); + } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { + + /* RSDP has no common fields */ + + ACPI_MEMCPY(local_header.oem_id, + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); + + ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", + ACPI_CAST_PTR(void, address), + (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> + revision > + 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->length : 20, + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->revision, + local_header.oem_id)); + } else { + /* Standard ACPI table with full common header */ + + acpi_tb_cleanup_table_header(&local_header, header); + + ACPI_INFO((AE_INFO, + "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", + local_header.signature, ACPI_CAST_PTR(void, address), + local_header.length, local_header.revision, + local_header.oem_id, local_header.oem_table_id, + local_header.oem_revision, + local_header.asl_compiler_id, + local_header.asl_compiler_revision)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_validate_checksum + * + * PARAMETERS: table - ACPI table to verify + * length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns + * exception on bad checksum. + * + ******************************************************************************/ + +acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) +{ + u8 checksum; + + /* Compute the checksum on the table */ + + checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); + + /* Checksum ok? (should be zero) */ + + if (checksum) { + ACPI_BIOS_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", + table->signature, table->checksum, + (u8)(table->checksum - checksum))); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_checksum + * + * PARAMETERS: buffer - Pointer to memory region to be checked + * length - Length of this memory region + * + * RETURN: Checksum (u8) + * + * DESCRIPTION: Calculates circular checksum of memory region. + * + ******************************************************************************/ + +u8 acpi_tb_checksum(u8 *buffer, u32 length) +{ + u8 sum = 0; + u8 *end = buffer + length; + + while (buffer < end) { + sum = (u8)(sum + *(buffer++)); + } + + return (sum); +} diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index ce3d5db39a9..bffdfc7b832 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: tbutils - table utilities + * Module Name: tbutils - ACPI Table utilities * *****************************************************************************/ @@ -49,12 +49,6 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ -static void acpi_tb_fix_string(char *string, acpi_size length); - -static void -acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, - struct acpi_table_header *header); - static acpi_physical_address acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); @@ -174,189 +168,6 @@ u8 acpi_tb_tables_loaded(void) return (FALSE); } -/******************************************************************************* - * - * FUNCTION: acpi_tb_fix_string - * - * PARAMETERS: string - String to be repaired - * length - Maximum length - * - * RETURN: None - * - * DESCRIPTION: Replace every non-printable or non-ascii byte in the string - * with a question mark '?'. - * - ******************************************************************************/ - -static void acpi_tb_fix_string(char *string, acpi_size length) -{ - - while (length && *string) { - if (!ACPI_IS_PRINT(*string)) { - *string = '?'; - } - string++; - length--; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_cleanup_table_header - * - * PARAMETERS: out_header - Where the cleaned header is returned - * header - Input ACPI table header - * - * RETURN: Returns the cleaned header in out_header - * - * DESCRIPTION: Copy the table header and ensure that all "string" fields in - * the header consist of printable characters. - * - ******************************************************************************/ - -static void -acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, - struct acpi_table_header *header) -{ - - ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); - - acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); - acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); - acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); - acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_print_table_header - * - * PARAMETERS: address - Table physical address - * header - Table header - * - * RETURN: None - * - * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. - * - ******************************************************************************/ - -void -acpi_tb_print_table_header(acpi_physical_address address, - struct acpi_table_header *header) -{ - struct acpi_table_header local_header; - - /* - * The reason that the Address is cast to a void pointer is so that we - * can use %p which will work properly on both 32-bit and 64-bit hosts. - */ - if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { - - /* FACS only has signature and length fields */ - - ACPI_INFO((AE_INFO, "%4.4s %p %05X", - header->signature, ACPI_CAST_PTR(void, address), - header->length)); - } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { - - /* RSDP has no common fields */ - - ACPI_MEMCPY(local_header.oem_id, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->oem_id, ACPI_OEM_ID_SIZE); - acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); - - ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", - ACPI_CAST_PTR (void, address), - (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> - revision > - 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->length : 20, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->revision, - local_header.oem_id)); - } else { - /* Standard ACPI table with full common header */ - - acpi_tb_cleanup_table_header(&local_header, header); - - ACPI_INFO((AE_INFO, - "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", - local_header.signature, ACPI_CAST_PTR(void, address), - local_header.length, local_header.revision, - local_header.oem_id, local_header.oem_table_id, - local_header.oem_revision, - local_header.asl_compiler_id, - local_header.asl_compiler_revision)); - - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_validate_checksum - * - * PARAMETERS: table - ACPI table to verify - * length - Length of entire table - * - * RETURN: Status - * - * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns - * exception on bad checksum. - * - ******************************************************************************/ - -acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) -{ - u8 checksum; - - /* Compute the checksum on the table */ - - checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); - - /* Checksum ok? (should be zero) */ - - if (checksum) { - ACPI_BIOS_WARNING((AE_INFO, - "Incorrect checksum in table [%4.4s] - 0x%2.2X, " - "should be 0x%2.2X", - table->signature, table->checksum, - (u8)(table->checksum - checksum))); - -#if (ACPI_CHECKSUM_ABORT) - - return (AE_BAD_CHECKSUM); -#endif - } - - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_checksum - * - * PARAMETERS: buffer - Pointer to memory region to be checked - * length - Length of this memory region - * - * RETURN: Checksum (u8) - * - * DESCRIPTION: Calculates circular checksum of memory region. - * - ******************************************************************************/ - -u8 acpi_tb_checksum(u8 *buffer, u32 length) -{ - u8 sum = 0; - u8 *end = buffer + length; - - while (buffer < end) { - sum = (u8) (sum + *(buffer++)); - } - - return (sum); -} - /******************************************************************************* * * FUNCTION: acpi_tb_check_dsdt_header -- cgit v1.2.3-70-g09d2 From 7cec7048fe22e3e92389da2cd67098f6c4284e7f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Sat, 8 Jun 2013 00:59:18 +0000 Subject: ACPICA: Do not use extended sleep registers unless HW-reduced bit is set Previous implementation incorrectly used the ACPI 5.0 extended sleep registers if they were simply populated. This caused problems on some non-HW-reduced machines. As per the ACPI spec, they should only be used if the HW-reduced bit is set. Lv Zheng, ACPICA BZ 1020. References: https://bugzilla.kernel.org/show_bug.cgi?id=54181 References: https://bugs.acpica.org/show_bug.cgi?id=1020 Reported-by: Daniel Rowe Bisected-by: Brint E. Kriebel Cc: 3.4+ Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwxfsleep.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index 111849c2117..f2e669db8b6 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -240,12 +240,14 @@ static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) &acpi_sleep_dispatch[function_id]; #if (!ACPI_REDUCED_HARDWARE) - /* * If the Hardware Reduced flag is set (from the FADT), we must - * use the extended sleep registers + * use the extended sleep registers (FADT). Note: As per the ACPI + * specification, these extended registers are to be used for HW-reduced + * platforms only. They are not general-purpose replacements for the + * legacy PM register sleep support. */ - if (acpi_gbl_reduced_hardware || acpi_gbl_FADT.sleep_control.address) { + if (acpi_gbl_reduced_hardware) { status = sleep_functions->extended_function(sleep_state); } else { /* Legacy sleep */ -- cgit v1.2.3-70-g09d2 From de8e7db74a98124406b72a528f4c79766e08b410 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Sat, 8 Jun 2013 00:59:44 +0000 Subject: ACPICA: Update interface to acpi_ut_valid_acpi_name() Clean up the interface by making the input argument a char * string instead of a UINT32 name. This is easier to use for all callers and eliminates casting to *(UINT32*) Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acutils.h | 2 +- drivers/acpi/acpica/tbinstal.c | 3 +-- drivers/acpi/acpica/utstring.c | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index d552036935d..3c76edea680 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -620,7 +620,7 @@ 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_name(char *name); u8 acpi_ut_valid_acpi_char(char character, u32 position); diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index a04e54d984d..42a13c0d701 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -141,8 +141,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) ACPI_BIOS_ERROR((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " "must be SSDT or OEMx", - acpi_ut_valid_acpi_name(*(u32 *)table_desc-> - pointer-> + acpi_ut_valid_acpi_name(table_desc->pointer-> signature) ? table_desc->pointer->signature : "????", *(u32 *)table_desc->pointer->signature)); diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 31a06a17e29..c53759b76a3 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -462,7 +462,8 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position) * * FUNCTION: acpi_ut_valid_acpi_name * - * PARAMETERS: name - The name to be examined + * PARAMETERS: name - The name to be examined. Does not have to + * be NULL terminated string. * * RETURN: TRUE if the name is valid, FALSE otherwise * @@ -473,15 +474,14 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position) * ******************************************************************************/ -u8 acpi_ut_valid_acpi_name(u32 name) +u8 acpi_ut_valid_acpi_name(char *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)) { + if (!acpi_ut_valid_acpi_char(name[i], i)) { return (FALSE); } } -- cgit v1.2.3-70-g09d2 From 9dae7bb0459332cc8fe8e29880cd158807c03d6b Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Sat, 8 Jun 2013 00:59:55 +0000 Subject: ACPICA: ACPICA Termination: Delete global lock pending lock Add deletion of this lock, used for the global lock. ACPICA BZ 1012. Tomasz Nowicki References: https://bugs.acpica.org/show_bug.cgi?id=1012 Signed-off-by: Tomasz Nowicki Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evglock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index a621481c6cf..fdb0a76e40a 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -128,6 +128,7 @@ acpi_status acpi_ev_remove_global_lock_handler(void) status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL, acpi_ev_global_lock_handler); + acpi_os_delete_lock(acpi_gbl_global_lock_pending_lock); return_ACPI_STATUS(status); } -- cgit v1.2.3-70-g09d2 From b739f106cb6385b83bac41e1f417c4e9347171a4 Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Sat, 8 Jun 2013 01:00:07 +0000 Subject: ACPICA: Fix possible memory leak in GPE init error path Some GPE blocks were not deleted. ACPICA BZ 1018. Tomasz Nowicki References: https://bugs.acpica.org/show_bug.cgi?id=1018 Signed-off-by: Tomasz Nowicki Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evgpeblk.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index a2d688bbac0..c1aa1eda26c 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -382,6 +382,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); if (ACPI_FAILURE(status)) { + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block->event_info); ACPI_FREE(gpe_block); return_ACPI_STATUS(status); } -- cgit v1.2.3-70-g09d2 From 64f3af5fd1405b6856ef6eef555e72d7ea67ee14 Mon Sep 17 00:00:00 2001 From: Tomasz Nowicki Date: Sat, 8 Jun 2013 01:00:23 +0000 Subject: ACPICA: Clear events initialized flag upon event component termination Clear this flag to allow clean startup and even double termination. ACPICA BZ 1013. Tomasz Nowicki References: https://bugs.acpica.org/show_bug.cgi?id=1013 Signed-off-by: Tomasz Nowicki Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Reviewed-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evmisc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index db59fe3f639..1b111ef7490 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -276,6 +276,8 @@ void acpi_ev_terminate(void) ACPI_ERROR((AE_INFO, "Could not remove Global Lock handler")); } + + acpi_gbl_events_initialized = FALSE; } /* Deallocate all handler objects installed within GPE info structs */ -- cgit v1.2.3-70-g09d2 From f627217064dbef1eef53ceb01edb9c94203991e0 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 13 May 2013 12:42:44 +0000 Subject: ACPI / LPSS: add support for Intel BayTrail Intel BayTrail has almost the same Low Power Subsystem than Lynxpoint with few differences. Peripherals are clocked with different speeds (typically lower) and the clock is not always gated. To support this we add possibility to share a common fixed rate clock and make clock gating optional. Signed-off-by: Mika Westerberg Acked-by: Mike Turquette Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- drivers/clk/x86/clk-lpt.c | 4 +-- 2 files changed, 82 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 652fd5ce303..f6d760581fa 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -33,11 +33,19 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_SW_LTR 0x10 #define LPSS_AUTO_LTR 0x14 +struct lpss_shared_clock { + const char *name; + unsigned long rate; + struct clk *clk; +}; + struct lpss_device_desc { bool clk_required; const char *clkdev_name; bool ltr_required; unsigned int prv_offset; + bool clk_gate; + struct lpss_shared_clock *shared_clock; }; static struct lpss_device_desc lpss_dma_desc = { @@ -56,6 +64,7 @@ static struct lpss_device_desc lpt_dev_desc = { .clk_required = true, .prv_offset = 0x800, .ltr_required = true, + .clk_gate = true, }; static struct lpss_device_desc lpt_sdio_dev_desc = { @@ -63,6 +72,45 @@ static struct lpss_device_desc lpt_sdio_dev_desc = { .ltr_required = true, }; +static struct lpss_shared_clock uart_clock = { + .name = "uart_clk", + .rate = 44236800, +}; + +static struct lpss_device_desc byt_uart_dev_desc = { + .clk_required = true, + .prv_offset = 0x800, + .clk_gate = true, + .shared_clock = &uart_clock, +}; + +static struct lpss_shared_clock spi_clock = { + .name = "spi_clk", + .rate = 50000000, +}; + +static struct lpss_device_desc byt_spi_dev_desc = { + .clk_required = true, + .prv_offset = 0x400, + .clk_gate = true, + .shared_clock = &spi_clock, +}; + +static struct lpss_device_desc byt_sdio_dev_desc = { + .clk_required = true, +}; + +static struct lpss_shared_clock i2c_clock = { + .name = "i2c_clk", + .rate = 100000000, +}; + +static struct lpss_device_desc byt_i2c_dev_desc = { + .clk_required = true, + .prv_offset = 0x800, + .shared_clock = &i2c_clock, +}; + static const struct acpi_device_id acpi_lpss_device_ids[] = { /* Generic LPSS devices */ { "INTL9C60", (unsigned long)&lpss_dma_desc }, @@ -77,6 +125,13 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, { "INT33C7", }, + /* BayTrail LPSS devices */ + { "80860F0A", (unsigned long)&byt_uart_dev_desc }, + { "80860F0E", (unsigned long)&byt_spi_dev_desc }, + { "80860F14", (unsigned long)&byt_sdio_dev_desc }, + { "80860F41", (unsigned long)&byt_i2c_dev_desc }, + { "INT33B2", }, + { } }; @@ -98,7 +153,10 @@ static int register_device_clock(struct acpi_device *adev, struct lpss_private_data *pdata) { const struct lpss_device_desc *dev_desc = pdata->dev_desc; + struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; + struct clk *clk = ERR_PTR(-ENODEV); struct lpss_clk_data *clk_data; + const char *parent; if (!lpss_clk_dev) lpt_register_clock_device(); @@ -117,14 +175,30 @@ static int register_device_clock(struct acpi_device *adev, || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE) return -ENODATA; - pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev), - clk_data->name, 0, - pdata->mmio_base + dev_desc->prv_offset, - 0, 0, NULL); - if (IS_ERR(pdata->clk)) - return PTR_ERR(pdata->clk); + parent = clk_data->name; + + if (shared_clock) { + clk = shared_clock->clk; + if (!clk) { + clk = clk_register_fixed_rate(NULL, shared_clock->name, + "lpss_clk", 0, + shared_clock->rate); + shared_clock->clk = clk; + } + parent = shared_clock->name; + } + + if (dev_desc->clk_gate) { + clk = clk_register_gate(NULL, dev_name(&adev->dev), parent, 0, + pdata->mmio_base + dev_desc->prv_offset, + 0, 0, NULL); + pdata->clk = clk; + } + + if (IS_ERR(clk)) + return PTR_ERR(clk); - clk_register_clkdev(pdata->clk, NULL, dev_name(&adev->dev)); + clk_register_clkdev(clk, NULL, dev_name(&adev->dev)); return 0; } diff --git a/drivers/clk/x86/clk-lpt.c b/drivers/clk/x86/clk-lpt.c index 4f45eee9e33..812f83f8b0c 100644 --- a/drivers/clk/x86/clk-lpt.c +++ b/drivers/clk/x86/clk-lpt.c @@ -1,5 +1,5 @@ /* - * Intel Lynxpoint LPSS clocks. + * Intel Low Power Subsystem clocks. * * Copyright (C) 2013, Intel Corporation * Authors: Mika Westerberg @@ -18,8 +18,6 @@ #include #include -#define PRV_CLOCK_PARAMS 0x800 - static int lpt_clk_probe(struct platform_device *pdev) { struct lpss_clk_data *drvdata; -- cgit v1.2.3-70-g09d2 From 06d8641504726322fca54400bbac982bd44f9a27 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 17 Jun 2013 13:25:46 +0300 Subject: ACPI / LPSS: mask the UART TX completion interrupt Intel LPSS provides an extra TX byte counter and an extra TX completion interrupt for some of its bus controllers. However, there is no use for the extra UART interrupt and it has to be masked out during initialization. Otherwise, if the firmware does not mask the interrupt and the driver does not clear it, it may cause an interrupt flood freezing the board to happen. Add code masking that problematic interrupt to the ACPI LPSS driver. [rjw: Changelog] Signed-off-by: Heikki Krogerus Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f6d760581fa..bd9867f592b 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -32,6 +32,8 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_GENERAL_LTR_MODE_SW BIT(2) #define LPSS_SW_LTR 0x10 #define LPSS_AUTO_LTR 0x14 +#define LPSS_TX_INT 0x20 +#define LPSS_TX_INT_MASK BIT(1) struct lpss_shared_clock { const char *name; @@ -39,6 +41,8 @@ struct lpss_shared_clock { struct clk *clk; }; +struct lpss_private_data; + struct lpss_device_desc { bool clk_required; const char *clkdev_name; @@ -46,6 +50,7 @@ struct lpss_device_desc { unsigned int prv_offset; bool clk_gate; struct lpss_shared_clock *shared_clock; + void (*setup)(struct lpss_private_data *pdata); }; static struct lpss_device_desc lpss_dma_desc = { @@ -60,6 +65,15 @@ struct lpss_private_data { const struct lpss_device_desc *dev_desc; }; +static void lpss_uart_setup(struct lpss_private_data *pdata) +{ + unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; + u32 reg; + + reg = readl(pdata->mmio_base + tx_int_offset); + writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset); +} + static struct lpss_device_desc lpt_dev_desc = { .clk_required = true, .prv_offset = 0x800, @@ -67,6 +81,14 @@ static struct lpss_device_desc lpt_dev_desc = { .clk_gate = true, }; +static struct lpss_device_desc lpt_uart_dev_desc = { + .clk_required = true, + .prv_offset = 0x800, + .ltr_required = true, + .clk_gate = true, + .setup = lpss_uart_setup, +}; + static struct lpss_device_desc lpt_sdio_dev_desc = { .prv_offset = 0x1000, .ltr_required = true, @@ -82,6 +104,7 @@ static struct lpss_device_desc byt_uart_dev_desc = { .prv_offset = 0x800, .clk_gate = true, .shared_clock = &uart_clock, + .setup = lpss_uart_setup, }; static struct lpss_shared_clock spi_clock = { @@ -120,8 +143,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33C1", (unsigned long)&lpt_dev_desc }, { "INT33C2", (unsigned long)&lpt_dev_desc }, { "INT33C3", (unsigned long)&lpt_dev_desc }, - { "INT33C4", (unsigned long)&lpt_dev_desc }, - { "INT33C5", (unsigned long)&lpt_dev_desc }, + { "INT33C4", (unsigned long)&lpt_uart_dev_desc }, + { "INT33C5", (unsigned long)&lpt_uart_dev_desc }, { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, { "INT33C7", }, @@ -247,6 +270,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev, } } + if (dev_desc->setup) + dev_desc->setup(pdata); + adev->driver_data = pdata; ret = acpi_create_platform_device(adev, id); if (ret > 0) -- cgit v1.2.3-70-g09d2 From 958c4eb2aa325099ea1f54c7354e381e3d79f3ae Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 18 Jun 2013 16:51:35 +0300 Subject: ACPI / LPSS: override SDIO private register space size from ACPI tables The SDIO device in Lynxpoint has its LTR registers reserved for a WiFi device (a child of the SDIO device) in the ACPI namespace even though those registers physically belong to the SDIO device itself. In order to be able to access the SDIO LTR registers from the ACPI LPSS driver for diagnostic purposes we need to use a size override for the SDIO private register space. Add a possibility to override the size of the private register space of an LPSS device provided by the ACPI tables in the ACPI LPSS driver and set the correct size for the SDIO device in there. [rjw: Changelog] Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index bd9867f592b..a4e8c0337a5 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -48,6 +48,7 @@ struct lpss_device_desc { const char *clkdev_name; bool ltr_required; unsigned int prv_offset; + size_t prv_size_override; bool clk_gate; struct lpss_shared_clock *shared_clock; void (*setup)(struct lpss_private_data *pdata); @@ -91,6 +92,7 @@ static struct lpss_device_desc lpt_uart_dev_desc = { static struct lpss_device_desc lpt_sdio_dev_desc = { .prv_offset = 0x1000, + .prv_size_override = 0x1018, .ltr_required = true, }; @@ -249,7 +251,10 @@ static int acpi_lpss_create_device(struct acpi_device *adev, list_for_each_entry(rentry, &resource_list, node) if (resource_type(&rentry->res) == IORESOURCE_MEM) { - pdata->mmio_size = resource_size(&rentry->res); + if (dev_desc->prv_size_override) + pdata->mmio_size = dev_desc->prv_size_override; + else + pdata->mmio_size = resource_size(&rentry->res); pdata->mmio_base = ioremap(rentry->res.start, pdata->mmio_size); pdata->dev_desc = dev_desc; -- cgit v1.2.3-70-g09d2 From ecde3003e5205a283b46b931c729a2aecab64ba1 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Wed, 22 May 2013 14:59:11 +0200 Subject: ACPI / EC: access user space with get_user()/put_user() User space pointer may not be dereferenced. Use get_user()/put_user() instead and check their return codes. Signed-off-by: Vasiliy Kulikov Signed-off-by: Thomas Renninger Signed-off-by: Jiri Slaby Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec_sys.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c index 7586544fddb..4e7b798900f 100644 --- a/drivers/acpi/ec_sys.c +++ b/drivers/acpi/ec_sys.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "internal.h" MODULE_AUTHOR("Thomas Renninger "); @@ -34,7 +35,6 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf, * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private; */ unsigned int size = EC_SPACE_SIZE; - u8 *data = (u8 *) buf; loff_t init_off = *off; int err = 0; @@ -47,9 +47,15 @@ static ssize_t acpi_ec_read_io(struct file *f, char __user *buf, size = count; while (size) { - err = ec_read(*off, &data[*off - init_off]); + u8 byte_read; + err = ec_read(*off, &byte_read); if (err) return err; + if (put_user(byte_read, buf + *off - init_off)) { + if (*off - init_off) + return *off - init_off; /* partial read */ + return -EFAULT; + } *off += 1; size--; } @@ -65,7 +71,6 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, unsigned int size = count; loff_t init_off = *off; - u8 *data = (u8 *) buf; int err = 0; if (*off >= EC_SPACE_SIZE) @@ -76,7 +81,12 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf, } while (size) { - u8 byte_write = data[*off - init_off]; + u8 byte_write; + if (get_user(byte_write, buf + *off - init_off)) { + if (*off - init_off) + return *off - init_off; /* partial write */ + return -EFAULT; + } err = ec_write(*off, byte_write); if (err) return err; -- cgit v1.2.3-70-g09d2 From c7d9ca90aa9497f0b6e301ec67c52dd4b57a7852 Mon Sep 17 00:00:00 2001 From: Jeff Wu Date: Wed, 29 May 2013 06:31:30 +0000 Subject: ACPI: add _STA evaluation at do_acpi_find_child() Once do_acpi_find_child() has found the first matching handle, it makes the acpi_get_child() loop stop and return that handle. On some platforms, though, there are multiple devices with the same value of "_ADR" in the same namespace scope, and if one of them is enabled, the others will be disabled. For example: Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV0 Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV1 Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV2 If DEV0 and DEV1 are disabled and DEV2 is enabled, the handle of DEV2 should be returned, but actually the function always returns the handle of DEV0. To address that issue, make do_acpi_find_child() evaluate _STA to check the device status. If a matching device object exists, but is disabled, acpi_get_child() will continue to walk the namespace in the hope of finding an enabled one. If one is found, its handle will be returned, but otherwise the function will return the handle of the disabled object found before (in case it is enabled going forward). [rjw: Changelog] Signed-off-by: Jeff Wu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/glue.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 40a84cc6740..51ca764cffe 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -81,13 +81,15 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, void *addr_p, void **ret_p) { - unsigned long long addr; + unsigned long long addr, sta; acpi_status status; 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; + status = acpi_bus_get_status_handle(handle, &sta); + if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_ENABLED)) + return AE_CTRL_TERMINATE; } return AE_OK; } -- cgit v1.2.3-70-g09d2 From 0f4c65478d2ac03296415a5bdac1ead3e24cfc5b Mon Sep 17 00:00:00 2001 From: Nicholas Mazzuca Date: Wed, 8 May 2013 23:11:15 +0000 Subject: ACPI / battery: Make sure all spaces are in correct places Add or remove spaces that give errors or warnings from checkpatch.pl. Signed-off-by: Nicholas Mazzuca Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index e7100459ac4..082b4dd252a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -425,7 +425,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) { int result = -EFAULT; acpi_status status = 0; - char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)? + char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ? "_BIX" : "_BIF"; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -661,11 +661,11 @@ static void find_battery(const struct dmi_header *dm, void *private) static void acpi_battery_quirks(struct acpi_battery *battery) { if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) - return ; + return; - if (battery->full_charge_capacity == 100 && - battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && - battery->capacity_now >=0 && battery->capacity_now <= 100) { + if (battery->full_charge_capacity == 100 && + battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && + battery->capacity_now >= 0 && battery->capacity_now <= 100) { set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags); battery->full_charge_capacity = battery->design_capacity; battery->capacity_now = (battery->capacity_now * @@ -673,7 +673,7 @@ static void acpi_battery_quirks(struct acpi_battery *battery) } if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags)) - return ; + return; if (battery->power_unit && dmi_name_in_vendors("LENOVO")) { const char *s; @@ -761,7 +761,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) goto end; seq_printf(seq, "present: %s\n", - acpi_battery_present(battery)?"yes":"no"); + acpi_battery_present(battery) ? "yes" : "no"); if (!acpi_battery_present(battery)) goto end; if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) @@ -817,12 +817,12 @@ static int acpi_battery_print_state(struct seq_file *seq, int result) goto end; seq_printf(seq, "present: %s\n", - acpi_battery_present(battery)?"yes":"no"); + acpi_battery_present(battery) ? "yes" : "no"); if (!acpi_battery_present(battery)) goto end; seq_printf(seq, "capacity state: %s\n", - (battery->state & 0x04)?"critical":"ok"); + (battery->state & 0x04) ? "critical" : "ok"); if ((battery->state & 0x01) && (battery->state & 0x02)) seq_printf(seq, "charging state: charging/discharging\n"); -- cgit v1.2.3-70-g09d2 From 6a8c0af6e2d6c472517959b66c96900151c9cb5b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 3 Jun 2013 18:20:24 +0000 Subject: ACPI: Remove useless initializers These local variables are all initialized at their first use, so there's no point in initializing them earlier. Signed-off-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 292de3cab9c..a5bb33bab44 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -91,8 +91,7 @@ static struct dmi_system_id dsdt_dmi_table[] __initdata = { int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) { - acpi_status status = AE_OK; - + acpi_status status; if (!device) return -EINVAL; @@ -162,7 +161,7 @@ EXPORT_SYMBOL(acpi_bus_private_data_handler); int acpi_bus_get_private_data(acpi_handle handle, void **data) { - acpi_status status = AE_OK; + acpi_status status; if (!*data) return -EINVAL; @@ -361,7 +360,7 @@ extern int event_is_open; int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data) { struct acpi_bus_event *event; - unsigned long flags = 0; + unsigned long flags; /* drop event on the floor if no one's listening */ if (!event_is_open) @@ -400,7 +399,7 @@ EXPORT_SYMBOL(acpi_bus_generate_proc_event); int acpi_bus_receive_event(struct acpi_bus_event *event) { - unsigned long flags = 0; + unsigned long flags; struct acpi_bus_event *entry = NULL; DECLARE_WAITQUEUE(wait, current); @@ -593,7 +592,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) static int __init acpi_bus_init_irq(void) { - acpi_status status = AE_OK; + acpi_status status; union acpi_object arg = { ACPI_TYPE_INTEGER }; struct acpi_object_list arg_list = { 1, &arg }; char *message = NULL; @@ -640,7 +639,7 @@ u8 acpi_gbl_permanent_mmap; void __init acpi_early_init(void) { - acpi_status status = AE_OK; + acpi_status status; if (acpi_disabled) return; @@ -714,8 +713,8 @@ void __init acpi_early_init(void) static int __init acpi_bus_init(void) { - int result = 0; - acpi_status status = AE_OK; + int result; + acpi_status status; extern acpi_status acpi_os_initialize1(void); acpi_os_initialize1(); -- cgit v1.2.3-70-g09d2 From d6a77ead21b69c395ca6d09a066ededfac601bcc Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 14 May 2013 17:09:16 +0000 Subject: x86 / ACPI / sleep: Provide registration for acpi_suspend_lowlevel. Which by default will be x86_acpi_suspend_lowlevel. This registration allows us to register another callback if there is a need to use another platform specific callback. Signed-off-by: Liang Tang Signed-off-by: Konrad Rzeszutek Wilk Tested-by: Ben Guthro Acked-by: "H. Peter Anvin" Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/acpi.h | 2 +- arch/x86/kernel/acpi/boot.c | 7 +++++++ arch/x86/kernel/acpi/sleep.c | 4 ++-- arch/x86/kernel/acpi/sleep.h | 2 ++ drivers/acpi/sleep.c | 2 ++ 5 files changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index b31bf97775f..2dfac58f3b1 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -111,7 +111,7 @@ static inline void acpi_disable_pci(void) } /* Low-level suspend routine. */ -extern int acpi_suspend_lowlevel(void); +extern int (*acpi_suspend_lowlevel)(void); /* Physical address to resume after wakeup */ #define acpi_wakeup_address ((unsigned long)(real_mode_header->wakeup_start)) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 230c8ea878e..d81a972dd50 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -44,6 +44,7 @@ #include #include +#include "sleep.h" /* To include x86_acpi_suspend_lowlevel */ static int __initdata acpi_force = 0; u32 acpi_rsdt_forced; int acpi_disabled; @@ -559,6 +560,12 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi, int (*__acpi_register_gsi)(struct device *dev, u32 gsi, int trigger, int polarity) = acpi_register_gsi_pic; +#ifdef CONFIG_ACPI_SLEEP +int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel; +#else +int (*acpi_suspend_lowlevel)(void); +#endif + /* * success: return IRQ number (>=0) * failure: return < 0 diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index b44577bc974..2a34aaf3c8f 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -26,12 +26,12 @@ static char temp_stack[4096]; #endif /** - * acpi_suspend_lowlevel - save kernel state + * x86_acpi_suspend_lowlevel - save kernel state * * Create an identity mapped page table and copy the wakeup routine to * low memory. */ -int acpi_suspend_lowlevel(void) +int x86_acpi_suspend_lowlevel(void) { struct wakeup_header *header = (struct wakeup_header *) __va(real_mode_header->wakeup_header); diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 67f59f8c695..c9c2c982d5e 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -15,3 +15,5 @@ extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); extern void do_suspend_lowlevel(void); + +extern int x86_acpi_suspend_lowlevel(void); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 9c1a435d10e..187ab61889e 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -494,6 +494,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) break; case ACPI_STATE_S3: + if (!acpi_suspend_lowlevel) + return -ENOSYS; error = acpi_suspend_lowlevel(); if (error) return error; -- cgit v1.2.3-70-g09d2 From 95d45d4cab6540e3f2183d86662c255fa4332331 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Tue, 11 Jun 2013 00:55:10 +0200 Subject: ACPI / PM: acpi_processor_suspend() can be static Since acpi_processor_suspend() and acpi_processor_resume() need not be visible outside of the file they are defined in, make them static. [rjw: Changelog] Signed-off-by: Fengguang Wu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_idle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index eb133c77aad..0461ccc92c5 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -214,13 +214,13 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr, #ifdef CONFIG_PM_SLEEP static u32 saved_bm_rld; -int acpi_processor_suspend(void) +static int acpi_processor_suspend(void) { acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld); return 0; } -void acpi_processor_resume(void) +static void acpi_processor_resume(void) { u32 resumed_bm_rld; -- cgit v1.2.3-70-g09d2 From b25c77efa71178f8281401e492e5c63cf7c34900 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 16 Jun 2013 00:37:42 +0200 Subject: ACPI / PM: Rename function acpi_device_power_state() and make it static There is a name clash between function acpi_device_power_state() defined in drivers/acpi/device_pm.c and structure type acpi_device_power_state defined in include/acpi/acpi_bus.h, which may be resolved by renaming the function. Additionally, that funtion may be made static, because it is not used anywhere outside of the file it is defined in. Rename acpi_device_power_state() to acpi_dev_pm_get_state(), which better reflects its purpose, and make it static. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 15 +++++++-------- include/acpi/acpi_bus.h | 16 ++-------------- 2 files changed, 9 insertions(+), 22 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 318fa32a141..26d3fd718a0 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -399,7 +399,7 @@ bool acpi_bus_can_wakeup(acpi_handle handle) EXPORT_SYMBOL(acpi_bus_can_wakeup); /** - * acpi_device_power_state - Get preferred power state of ACPI device. + * acpi_dev_pm_get_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. @@ -417,8 +417,8 @@ EXPORT_SYMBOL(acpi_bus_can_wakeup); * 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) +static int acpi_dev_pm_get_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; @@ -501,7 +501,6 @@ int acpi_device_power_state(struct device *dev, struct acpi_device *adev, } return d_max; } -EXPORT_SYMBOL_GPL(acpi_device_power_state); /** * acpi_pm_device_sleep_state - Get preferred power state of ACPI device. @@ -523,8 +522,8 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) return -ENODEV; } - return acpi_device_power_state(dev, adev, acpi_target_system_state(), - d_max_in, d_min_p); + return acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), + d_max_in, d_min_p); } EXPORT_SYMBOL(acpi_pm_device_sleep_state); @@ -680,8 +679,8 @@ static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, if (!acpi_device_power_manageable(adev)) return 0; - power_state = acpi_device_power_state(dev, adev, system_state, - ACPI_STATE_D3, NULL); + power_state = acpi_dev_pm_get_state(dev, adev, system_state, + ACPI_STATE_D3, NULL); if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3) return -EIO; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 636c59f2003..c3dc203a90f 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -467,8 +467,6 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, acpi_notify_handler handler, void *context); acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, acpi_notify_handler handler); -int acpi_device_power_state(struct device *dev, struct acpi_device *adev, - u32 target_state, int d_max_in, int *d_min_p); int acpi_pm_device_sleep_state(struct device *, int *, int); void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev); void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev); @@ -484,23 +482,13 @@ static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, { return AE_SUPPORT; } -static inline int __acpi_device_power_state(int m, int *p) +static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) { if (p) *p = ACPI_STATE_D0; + return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0; } -static inline int acpi_device_power_state(struct device *dev, - struct acpi_device *adev, - u32 target_state, int d_max_in, - int *d_min_p) -{ - return __acpi_device_power_state(d_max_in, d_min_p); -} -static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) -{ - return __acpi_device_power_state(m, p); -} static inline void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev) {} static inline void acpi_dev_pm_remove_dependent(acpi_handle handle, -- cgit v1.2.3-70-g09d2 From 4c164ae7d8a7ee1f39b773d97794535c2c193b12 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 16 Jun 2013 00:37:50 +0200 Subject: ACPI / PM: Replace ACPI_STATE_D3 with ACPI_STATE_D3_COLD in device_pm.c The two symbols ACPI_STATE_D3 and ACPI_STATE_D3_COLD actually represent the same number (4), but ACPI_STATE_D3 is slightly ambigugous, because it may not be clear that it really means D3cold and not D3hot at first sight. Remove that ambiguity from drivers/acpi/device_pm.c by making it use ACPI_STATE_D3_COLD everywhere instead of ACPI_STATE_D3. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 26d3fd718a0..afc808e9385 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -424,7 +424,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, unsigned long long d_min, d_max; bool wakeup = false; - if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3) + if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) return -EINVAL; if (d_max_in > ACPI_STATE_D3_HOT) { @@ -443,7 +443,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, * the lowest limit with the specified one. */ d_min = ACPI_STATE_D0; - d_max = ACPI_STATE_D3; + d_max = ACPI_STATE_D3_COLD; /* * If present, _SxD methods return the minimum D-state (highest power @@ -680,8 +680,8 @@ static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, return 0; power_state = acpi_dev_pm_get_state(dev, adev, system_state, - ACPI_STATE_D3, NULL); - if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3) + ACPI_STATE_D3_COLD, NULL); + if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3_COLD) return -EIO; return acpi_device_set_power(adev, power_state); -- cgit v1.2.3-70-g09d2 From fa1675b56537651270e79967b7f1ee4202c83bf6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 16 Jun 2013 00:37:59 +0200 Subject: ACPI / PM: Rework and clean up acpi_dev_pm_get_state() The acpi_dev_pm_get_state() function defined in device_pm.c is quite convoluted, which isn't really necessary, and it doesn't validate the values returned by the ACPI methods executed by it appropriately. To address these shortcomings modify it in the following way. (1) Make its return value only mean whether or not it succeeded and pass the device power states determined by it through pointers. (2) Drop the d_max_in argument, used by only one of its callers, from it, and move the code related to d_max_in into that caller, acpi_pm_device_sleep_state(). (3) Make it always check the return value of acpi_evaluate_integer() and handle failures as appropriate. Moreover, make it check if the values returned by the executed ACPI methods are not out of range. (4) Make it check if the values returned by the executed ACPI methods represent valid power states of the given device and handle situations in which that's not the case gracefully. Also update the kerneldoc comments of acpi_dev_pm_get_state() and acpi_pm_device_sleep_state() to reflect the code changes. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 158 +++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 66 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index afc808e9385..fd363b57a59 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -403,44 +403,37 @@ EXPORT_SYMBOL(acpi_bus_can_wakeup); * @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 + * @d_min_p: Location to store the highest power state available to the device. + * @d_max_p: Location to store the lowest power state available to the device. * - * 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. + * Find the lowest power (highest number) and highest power (lowest number) ACPI + * device power states that the device can be in while the system is in the + * state represented by @target_state. Store the integer numbers representing + * those stats in the memory locations pointed to by @d_max_p and @d_min_p, + * respectively. * * Callers must ensure that @dev and @adev are valid pointers and that @adev * actually corresponds to @dev before using this function. + * + * Returns 0 on success or -ENODATA when one of the ACPI methods fails or + * returns a value that doesn't make sense. The memory locations pointed to by + * @d_max_p and @d_min_p are only modified on success. */ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, - u32 target_state, int d_max_in, int *d_min_p) + u32 target_state, int *d_min_p, int *d_max_p) { - char acpi_method[] = "_SxD"; - unsigned long long d_min, d_max; + char method[] = { '_', 'S', '0' + target_state, 'D', '\0' }; + acpi_handle handle = adev->handle; + unsigned long long ret; + int d_min, d_max; bool wakeup = false; + acpi_status status; - if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) - 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. + * If the system state is S0, the lowest power state the device can be + * in is D3cold, unless the device has _S0W and is supposed to signal + * wakeup, in which case the return value of _S0W has to be used as the + * lowest power state available to the device. */ d_min = ACPI_STATE_D0; d_max = ACPI_STATE_D3_COLD; @@ -449,12 +442,30 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, * 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); + /* + * We rely on acpi_evaluate_integer() not clobbering the integer + * provided if AE_NOT_FOUND is returned. + */ + ret = d_min; + status = acpi_evaluate_integer(handle, method, NULL, &ret); + if ((ACPI_FAILURE(status) && status != AE_NOT_FOUND) + || ret > ACPI_STATE_D3_COLD) + return -ENODATA; + + /* + * We need to handle legacy systems where D3hot and D3cold are + * the same and 3 is returned in both cases, so fall back to + * D3cold if D3hot is not a valid state. + */ + if (!adev->power.states[ret].flags.valid) { + if (ret == ACPI_STATE_D3_HOT) + ret = ACPI_STATE_D3_COLD; + else + return -ENODATA; + } + d_min = ret; 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) != @@ -470,36 +481,29 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, * 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) + method[3] = 'W'; + status = acpi_evaluate_integer(handle, method, NULL, &ret); + if (status == AE_NOT_FOUND) { + if (target_state > ACPI_STATE_S0) 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; + } else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) { + /* Fall back to D3cold if ret is not a valid state. */ + if (!adev->power.states[ret].flags.valid) + ret = ACPI_STATE_D3_COLD; + + d_max = ret > d_min ? ret : d_min; + } else { + return -ENODATA; } } - 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; + + if (d_max_p) + *d_max_p = d_max; + + return 0; } /** @@ -508,7 +512,8 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, * @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 + * if there's no 'struct acpi_device' for @dev, -EINVAL if @d_max_in is + * incorrect, or -ENODATA on ACPI method failure. * * The caller must ensure that @dev is valid before using this function. */ @@ -516,14 +521,39 @@ 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; + int ret, d_max; + + if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) + 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; + } if (!handle || acpi_bus_get_device(handle, &adev)) { dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); return -ENODEV; } - return acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), - d_max_in, d_min_p); + ret = acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), + d_min_p, &d_max); + if (ret) + return ret; + + if (d_max_in < *d_min_p) + return -EINVAL; + + if (d_max > d_max_in) { + for (d_max = d_max_in; d_max > *d_min_p; d_max--) { + if (adev->power.states[d_max].flags.valid) + break; + } + } + return d_max; } EXPORT_SYMBOL(acpi_pm_device_sleep_state); @@ -674,17 +704,13 @@ struct acpi_device *acpi_dev_pm_get_node(struct device *dev) static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev, u32 system_state) { - int power_state; + int ret, state; if (!acpi_device_power_manageable(adev)) return 0; - power_state = acpi_dev_pm_get_state(dev, adev, system_state, - ACPI_STATE_D3_COLD, NULL); - if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3_COLD) - return -EIO; - - return acpi_device_set_power(adev, power_state); + ret = acpi_dev_pm_get_state(dev, adev, system_state, NULL, &state); + return ret ? ret : acpi_device_set_power(adev, state); } /** -- cgit v1.2.3-70-g09d2 From 24071f472d813fccacc1ef7356b1f41422a1b968 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 16 Jun 2013 00:36:41 +0200 Subject: ACPI / scan: Do not bind ACPI drivers to objects with scan handlers ACPI drivers must not be bound to device objects having scan handlers attatched to them, so make acpi_device_probe() fail with -EINVAL if the device object being probed has an ACPI scan handler. After this change the analogous check introduced into the ACPI video driver by commit 8c9b7a7 (ACPI / video: Do not bind to device objects with a scan handler) is not necessary any more and may be dropped, so drop it. Signed-off-by: Rafael J. Wysocki Tested-by: Tony Luck Acked-by: Toshi Kani --- drivers/acpi/scan.c | 3 +++ drivers/acpi/video.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4eeea226245..54529424a0a 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -822,6 +822,9 @@ static int acpi_device_probe(struct device *dev) struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver); int ret; + if (acpi_dev->handler) + return -EINVAL; + if (!acpi_drv->ops.add) return -ENOSYS; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 440eadf2d32..5d7075d2570 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1722,9 +1722,6 @@ static int acpi_video_bus_add(struct acpi_device *device) int error; acpi_status status; - if (device->handler) - return -EINVAL; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, device->parent->handle, 1, acpi_video_bus_match, NULL, -- cgit v1.2.3-70-g09d2 From aa6329c44bccedbd8b17094c1c1aee1d9a9de461 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Sat, 8 Jun 2013 09:01:01 +0800 Subject: ACPICA: Move _PRT repair into the standard complex repair module Moved this longstanding repair to the relatively new predefined name repair module. ACPICA BZ 783. Lv Zheng. No functional change. This change simply moves the repair code from where it was originally implemented to the (more recent) repair module where it now belongs. References: https://bugs.acpica.org/show_bug.cgi?id=783 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nspredef.c | 7 ++- drivers/acpi/acpica/nsrepair2.c | 114 +++++++++++++++++++++++++++++++--------- drivers/acpi/acpica/rscalc.c | 5 +- drivers/acpi/acpica/rscreate.c | 27 ---------- 4 files changed, 99 insertions(+), 54 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 600268d33aa..8d59ac2399e 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -158,7 +158,12 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node, info->parent_package = *return_object_ptr; status = acpi_ns_check_package(info, return_object_ptr); if (ACPI_FAILURE(status)) { - goto exit; + + /* We might be able to fix an operand type error (_PRT) */ + + if (status != AE_AML_OPERAND_TYPE) { + goto exit; + } } } diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index daac8daeaa9..aca9bdf74e1 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -86,6 +86,10 @@ static acpi_status acpi_ns_repair_HID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); +static acpi_status +acpi_ns_repair_PRT(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr); + static acpi_status acpi_ns_repair_PSS(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); @@ -121,6 +125,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements, * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs * _HID: Strings: uppercase all, remove any leading asterisk + * _PRT: Fix reversed source_name and source_index * _PSS: Sort the list descending by Power * _TSS: Sort the list descending by Power * @@ -137,6 +142,7 @@ static const struct acpi_repair_info acpi_ns_repairable_names[] = { {"_FDE", acpi_ns_repair_FDE}, {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ {"_HID", acpi_ns_repair_HID}, + {"_PRT", acpi_ns_repair_PRT}, {"_PSS", acpi_ns_repair_PSS}, {"_TSS", acpi_ns_repair_TSS}, {{0, 0, 0, 0}, NULL} /* Table terminator */ @@ -488,7 +494,7 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, /****************************************************************************** * - * FUNCTION: acpi_ns_repair_TSS + * FUNCTION: acpi_ns_repair_PRT * * PARAMETERS: info - Method execution information block * return_object_ptr - Pointer to the object returned from the @@ -496,38 +502,54 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, * * RETURN: Status. AE_OK if object is OK or was repaired successfully * - * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list - * descending by the power dissipation values. + * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed + * source_name and source_index field, a common BIOS bug. * *****************************************************************************/ static acpi_status -acpi_ns_repair_TSS(struct acpi_evaluate_info *info, +acpi_ns_repair_PRT(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { - union acpi_operand_object *return_object = *return_object_ptr; - acpi_status status; - struct acpi_namespace_node *node; + union acpi_operand_object *package_object = *return_object_ptr; + union acpi_operand_object **top_object_list; + union acpi_operand_object **sub_object_list; + union acpi_operand_object *obj_desc; + u32 element_count; + u32 index; - /* - * We can only sort the _TSS return package if there is no _PSS in the - * same scope. This is because if _PSS is present, the ACPI specification - * dictates that the _TSS Power Dissipation field is to be ignored, and - * therefore some BIOSs leave garbage values in the _TSS Power field(s). - * In this case, it is best to just return the _TSS package as-is. - * (May, 2011) - */ - status = acpi_ns_get_node(info->node, "^_PSS", - ACPI_NS_NO_UPSEARCH, &node); - if (ACPI_SUCCESS(status)) { - return (AE_OK); - } + /* Each element in the _PRT package is a subpackage */ - status = acpi_ns_check_sorted_list(info, return_object, 5, 1, - ACPI_SORT_DESCENDING, - "PowerDissipation"); + top_object_list = package_object->package.elements; + element_count = package_object->package.count; - return (status); + for (index = 0; index < element_count; index++) { + sub_object_list = (*top_object_list)->package.elements; + + /* + * If the BIOS has erroneously reversed the _PRT source_name (index 2) + * and the source_index (index 3), fix it. _PRT is important enough to + * workaround this BIOS error. This also provides compatibility with + * other ACPI implementations. + */ + obj_desc = sub_object_list[3]; + if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { + sub_object_list[3] = sub_object_list[2]; + sub_object_list[2] = obj_desc; + info->return_flags |= ACPI_OBJECT_REPAIRED; + + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "PRT[%X]: Fixed reversed SourceName and SourceIndex", + index)); + } + + /* Point to the next union acpi_operand_object in the top level package */ + + top_object_list++; + } + + return (AE_OK); } /****************************************************************************** @@ -599,6 +621,50 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info, return (AE_OK); } +/****************************************************************************** + * + * FUNCTION: acpi_ns_repair_TSS + * + * PARAMETERS: info - Method execution information block + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list + * descending by the power dissipation values. + * + *****************************************************************************/ + +static acpi_status +acpi_ns_repair_TSS(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + acpi_status status; + struct acpi_namespace_node *node; + + /* + * We can only sort the _TSS return package if there is no _PSS in the + * same scope. This is because if _PSS is present, the ACPI specification + * dictates that the _TSS Power Dissipation field is to be ignored, and + * therefore some BIOSs leave garbage values in the _TSS Power field(s). + * In this case, it is best to just return the _TSS package as-is. + * (May, 2011) + */ + status = acpi_ns_get_node(info->node, "^_PSS", + ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_SUCCESS(status)) { + return (AE_OK); + } + + status = acpi_ns_check_sorted_list(info, return_object, 5, 1, + ACPI_SORT_DESCENDING, + "PowerDissipation"); + + return (status); +} + /****************************************************************************** * * FUNCTION: acpi_ns_check_sorted_list diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 608ebb56b67..b62a0f4f4f9 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -652,8 +652,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, name_found = FALSE; - for (table_index = 0; table_index < 4 && !name_found; - table_index++) { + for (table_index = 0; + table_index < package_element->package.count + && !name_found; table_index++) { if (*sub_object_list && /* Null object allowed */ ((ACPI_TYPE_STRING == (*sub_object_list)->common.type) || diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index f8b55b426c9..65f3e1c5b59 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -273,17 +273,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, */ user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4); - /* Each element of the top-level package must also be a package */ - - if ((*top_object_list)->common.type != ACPI_TYPE_PACKAGE) { - ACPI_ERROR((AE_INFO, - "(PRT[%u]) Need sub-package, found %s", - index, - acpi_ut_get_object_type_name - (*top_object_list))); - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); - } - /* Each sub-package must be of length 4 */ if ((*top_object_list)->package.count != 4) { @@ -326,22 +315,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, user_prt->pin = (u32) obj_desc->integer.value; - /* - * If the BIOS has erroneously reversed the _PRT source_name (index 2) - * and the source_index (index 3), fix it. _PRT is important enough to - * workaround this BIOS error. This also provides compatibility with - * other ACPI implementations. - */ - obj_desc = sub_object_list[3]; - if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { - sub_object_list[3] = sub_object_list[2]; - sub_object_list[2] = obj_desc; - - ACPI_WARNING((AE_INFO, - "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed", - index)); - } - /* * 3) Third subobject: Dereference the PRT.source_name * The name may be unresolved (slack mode), so allow a null object -- cgit v1.2.3-70-g09d2 From 5a9792f3be74bfad2985b3f4c7afc9e6f6a3f798 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Sat, 8 Jun 2013 09:01:07 +0800 Subject: ACPICA: Add several repairs for _CST predefined name Sort list based on the C-state, remove invalid/zero entries. ACPICA BZ 890. Lv Zheng. Fixes these possible problems with the _CST object: 1. Sort the list ascending by C state type. 2. Ensure type cannot be zero. 3. A sub-package count of zero means _CST is meaningless. 4. Count must match the number of C state sub-packages. References: https://bugs.acpica.org/show_bug.cgi?id=890 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nspredef.c | 5 +- drivers/acpi/acpica/nsrepair2.c | 170 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 8d59ac2399e..24b71a01bf9 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -159,9 +159,10 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node, status = acpi_ns_check_package(info, return_object_ptr); if (ACPI_FAILURE(status)) { - /* We might be able to fix an operand type error (_PRT) */ + /* We might be able to fix some errors */ - if (status != AE_AML_OPERAND_TYPE) { + if ((status != AE_AML_OPERAND_TYPE) && + (status != AE_AML_OPERAND_VALUE)) { goto exit; } } diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index aca9bdf74e1..029816edd39 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -78,6 +78,10 @@ static acpi_status acpi_ns_repair_CID(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); +static acpi_status +acpi_ns_repair_CST(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr); + static acpi_status acpi_ns_repair_FDE(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr); @@ -101,19 +105,23 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info, static acpi_status acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, + u32 start_index, u32 expected_count, u32 sort_index, u8 sort_direction, char *sort_key_name); -static void -acpi_ns_sort_list(union acpi_operand_object **elements, - u32 count, u32 index, u8 sort_direction); - /* Values for sort_direction above */ #define ACPI_SORT_ASCENDING 0 #define ACPI_SORT_DESCENDING 1 +static void +acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index); + +static void +acpi_ns_sort_list(union acpi_operand_object **elements, + u32 count, u32 index, u8 sort_direction); + /* * This table contains the names of the predefined methods for which we can * perform more complex repairs. @@ -122,6 +130,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements, * * _ALR: Sort the list ascending by ambient_illuminance * _CID: Strings: uppercase all, remove any leading asterisk + * _CST: Sort the list ascending by C state type * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs * _HID: Strings: uppercase all, remove any leading asterisk @@ -139,6 +148,7 @@ acpi_ns_sort_list(union acpi_operand_object **elements, static const struct acpi_repair_info acpi_ns_repairable_names[] = { {"_ALR", acpi_ns_repair_ALR}, {"_CID", acpi_ns_repair_CID}, + {"_CST", acpi_ns_repair_CST}, {"_FDE", acpi_ns_repair_FDE}, {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ {"_HID", acpi_ns_repair_HID}, @@ -243,7 +253,7 @@ acpi_ns_repair_ALR(struct acpi_evaluate_info *info, union acpi_operand_object *return_object = *return_object_ptr; acpi_status status; - status = acpi_ns_check_sorted_list(info, return_object, 2, 1, + status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1, ACPI_SORT_ASCENDING, "AmbientIlluminance"); @@ -409,6 +419,92 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info, return (AE_OK); } +/****************************************************************************** + * + * FUNCTION: acpi_ns_repair_CST + * + * PARAMETERS: info - Method execution information block + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _CST object: + * 1. Sort the list ascending by C state type + * 2. Ensure type cannot be zero + * 3. A sub-package count of zero means _CST is meaningless + * 4. Count must match the number of C state sub-packages + * + *****************************************************************************/ + +static acpi_status +acpi_ns_repair_CST(struct acpi_evaluate_info *info, + union acpi_operand_object **return_object_ptr) +{ + union acpi_operand_object *return_object = *return_object_ptr; + union acpi_operand_object **outer_elements; + u32 outer_element_count; + union acpi_operand_object *obj_desc; + acpi_status status; + u8 removing; + u32 i; + + ACPI_FUNCTION_NAME(ns_repair_CST); + + /* + * Entries (subpackages) in the _CST Package must be sorted by the + * C-state type, in ascending order. + */ + status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1, + ACPI_SORT_ASCENDING, "C-State Type"); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* + * We now know the list is correctly sorted by C-state type. Check if + * the C-state type values are proportional. + */ + outer_element_count = return_object->package.count - 1; + i = 0; + while (i < outer_element_count) { + outer_elements = &return_object->package.elements[i + 1]; + removing = FALSE; + + if ((*outer_elements)->package.count == 0) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "SubPackage[%u] - removing entry due to zero count", + i)); + removing = TRUE; + goto remove_element; + } + + obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */ + if ((u32)obj_desc->integer.value == 0) { + ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, + info->node_flags, + "SubPackage[%u] - removing entry due to invalid Type(0)", + i)); + removing = TRUE; + } + + remove_element: + if (removing) { + acpi_ns_remove_element(return_object, i + 1); + outer_element_count--; + } else { + i++; + } + } + + /* Update top-level package count, Type "Integer" checked elsewhere */ + + obj_desc = return_object->package.elements[0]; + obj_desc->integer.value = outer_element_count; + return (AE_OK); +} + /****************************************************************************** * * FUNCTION: acpi_ns_repair_HID @@ -588,7 +684,7 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info, * incorrectly sorted, sort it. We sort by cpu_frequency, since this * should be proportional to the power. */ - status = acpi_ns_check_sorted_list(info, return_object, 6, 0, + status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0, ACPI_SORT_DESCENDING, "CpuFrequency"); if (ACPI_FAILURE(status)) { @@ -658,7 +754,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info, return (AE_OK); } - status = acpi_ns_check_sorted_list(info, return_object, 5, 1, + status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1, ACPI_SORT_DESCENDING, "PowerDissipation"); @@ -671,6 +767,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info, * * PARAMETERS: info - Method execution information block * return_object - Pointer to the top-level returned object + * start_index - Index of the first sub-package * expected_count - Minimum length of each sub-package * sort_index - Sub-package entry to sort on * sort_direction - Ascending or descending @@ -687,6 +784,7 @@ acpi_ns_repair_TSS(struct acpi_evaluate_info *info, static acpi_status acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, union acpi_operand_object *return_object, + u32 start_index, u32 expected_count, u32 sort_index, u8 sort_direction, char *sort_key_name) @@ -711,12 +809,14 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, * Any NULL elements should have been removed by earlier call * to acpi_ns_remove_null_elements. */ - outer_elements = return_object->package.elements; outer_element_count = return_object->package.count; - if (!outer_element_count) { + if (!outer_element_count || start_index >= outer_element_count) { return (AE_AML_PACKAGE_LIMIT); } + outer_elements = &return_object->package.elements[start_index]; + outer_element_count -= start_index; + previous_value = 0; if (sort_direction == ACPI_SORT_DESCENDING) { previous_value = ACPI_UINT32_MAX; @@ -753,7 +853,8 @@ acpi_ns_check_sorted_list(struct acpi_evaluate_info *info, (obj_desc->integer.value < previous_value)) || ((sort_direction == ACPI_SORT_DESCENDING) && (obj_desc->integer.value > previous_value))) { - acpi_ns_sort_list(return_object->package.elements, + acpi_ns_sort_list(&return_object->package. + elements[start_index], outer_element_count, sort_index, sort_direction); @@ -820,3 +921,52 @@ acpi_ns_sort_list(union acpi_operand_object **elements, } } } + +/****************************************************************************** + * + * FUNCTION: acpi_ns_remove_element + * + * PARAMETERS: obj_desc - Package object element list + * index - Index of element to remove + * + * RETURN: None + * + * DESCRIPTION: Remove the requested element of a package and delete it. + * + *****************************************************************************/ + +static void +acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index) +{ + union acpi_operand_object **source; + union acpi_operand_object **dest; + u32 count; + u32 new_count; + u32 i; + + ACPI_FUNCTION_NAME(ns_remove_element); + + count = obj_desc->package.count; + new_count = count - 1; + + source = obj_desc->package.elements; + dest = source; + + /* Examine all elements of the package object, remove matched index */ + + for (i = 0; i < count; i++) { + if (i == index) { + acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */ + acpi_ut_remove_reference(*source); + } else { + *dest = *source; + dest++; + } + source++; + } + + /* NULL terminate list and update the package count */ + + *dest = NULL; + obj_desc->package.count = new_count; +} -- cgit v1.2.3-70-g09d2 From 341e7ba1a9a48c50b46a1ebf305823f883c85d4f Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Sat, 8 Jun 2013 09:01:19 +0800 Subject: ACPICA: _CST repair: Handle null package entries Sort package only after null/bad elements have been removed. Fixes a problem where the _CST sort was performed too early. This change sorts the package only after null/bad elements have been removed. Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsrepair2.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 029816edd39..c84603ee83a 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -452,18 +452,7 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info, ACPI_FUNCTION_NAME(ns_repair_CST); /* - * Entries (subpackages) in the _CST Package must be sorted by the - * C-state type, in ascending order. - */ - status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1, - ACPI_SORT_ASCENDING, "C-State Type"); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * We now know the list is correctly sorted by C-state type. Check if - * the C-state type values are proportional. + * Check if the C-state type values are proportional. */ outer_element_count = return_object->package.count - 1; i = 0; @@ -502,6 +491,17 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info, obj_desc = return_object->package.elements[0]; obj_desc->integer.value = outer_element_count; + + /* + * Entries (subpackages) in the _CST Package must be sorted by the + * C-state type, in ascending order. + */ + status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1, + ACPI_SORT_ASCENDING, "C-State Type"); + if (ACPI_FAILURE(status)) { + return (status); + } + return (AE_OK); } -- cgit v1.2.3-70-g09d2 From 86d6725a572d08e5e709871a77a7df137adf5ad4 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Mon, 24 Jun 2013 15:36:33 +0800 Subject: ACPI / processor: Remove unused macros in processor_driver.c ACPI_PROCESSOR_FILE_INFO, ACPI_PROCESSOR_FILE_THROTTLING and ACPI_PROCESSOR_FILE_LIMIT are used for procfs, but this feature was removed in commit d09fe555 (ACPI processor: remove deprecated ACPI procfs I/F) long ago. So, these macros should also be removed. ACPI_PROCESSOR_LIMIT_USER and ACPI_PROCESSOR_LIMIT_THERMAL are not used by any code, remove them too. Signed-off-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_driver.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index d93963f1e8f..823be116619 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -43,16 +43,10 @@ #define PREFIX "ACPI: " -#define ACPI_PROCESSOR_FILE_INFO "info" -#define ACPI_PROCESSOR_FILE_THROTTLING "throttling" -#define ACPI_PROCESSOR_FILE_LIMIT "limit" #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 -#define ACPI_PROCESSOR_LIMIT_USER 0 -#define ACPI_PROCESSOR_LIMIT_THERMAL 1 - #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_driver"); -- cgit v1.2.3-70-g09d2 From 09d5ca804e796a20dbc50be0971b9e89e692c256 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Tue, 25 Jun 2013 10:06:45 +0800 Subject: ACPI / processor: Drop unused variable from processor_perflib.c The count variable in acpi_processor_preregister_performance() is only initalized as 1 for one CPU and incremented when another CPU sharing the same dependency domain is found. It isn't referenced anywhere else, so drop it. Signed-off-by: Lan Tianyu Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_perflib.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index e854582f29a..1e9732d809b 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -639,7 +639,7 @@ end: int acpi_processor_preregister_performance( struct acpi_processor_performance __percpu *performance) { - int count, count_target; + int count_target; int retval = 0; unsigned int i, j; cpumask_var_t covered_cpus; @@ -711,7 +711,6 @@ int acpi_processor_preregister_performance( /* Validate the Domain info */ count_target = pdomain->num_processors; - count = 1; if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL) pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) @@ -745,7 +744,6 @@ int acpi_processor_preregister_performance( cpumask_set_cpu(j, covered_cpus); cpumask_set_cpu(j, pr->performance->shared_cpu_map); - count++; } for_each_possible_cpu(j) { -- cgit v1.2.3-70-g09d2 From 2fa97feb4406c546b52e35b6b6c50cb8f63425d2 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Jun 2013 02:27:50 +0000 Subject: ACPI: Add CMOS RTC Operation Region handler support On HP Folio 13-2000, the BIOS defines a CMOS RTC Operation Region and the EC's _REG methord accesses that region. Thus an appropriate address space handler must be registered for that region before the EC driver is loaded. Introduce a mechanism for adding CMOS RTC address space handlers. Register an ACPI scan handler for CMOS RTC devices such that, when a device of that kind is detected during an ACPI namespace scan, a common CMOS RTC operation region address space handler will be installed for it. References: https://bugzilla.kernel.org/show_bug.cgi?id=54621 Reported-and-tested-by: Stefan Nagy Signed-off-by: Lan Tianyu Cc: 3.9+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 1 + drivers/acpi/acpi_cmos_rtc.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/internal.h | 5 +++ drivers/acpi/scan.c | 1 + 4 files changed, 99 insertions(+) create mode 100644 drivers/acpi/acpi_cmos_rtc.c (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 536562c626a..97c949abfab 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -43,6 +43,7 @@ acpi-y += acpi_platform.o acpi-y += power.o acpi-y += event.o acpi-y += sysfs.o +acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c new file mode 100644 index 00000000000..84190ed89c0 --- /dev/null +++ b/drivers/acpi/acpi_cmos_rtc.c @@ -0,0 +1,92 @@ +/* + * ACPI support for CMOS RTC Address Space access + * + * Copyright (C) 2013, Intel Corporation + * Authors: Lan Tianyu + * + * 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 +#include +#include +#include +#include +#include + +#include "internal.h" + +#define PREFIX "ACPI: " + +ACPI_MODULE_NAME("cmos rtc"); + +static const struct acpi_device_id acpi_cmos_rtc_ids[] = { + { "PNP0B00" }, + { "PNP0B01" }, + { "PNP0B02" }, + {} +}; + +static acpi_status +acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, + u32 bits, u64 *value64, + void *handler_context, void *region_context) +{ + int i; + u8 *value = (u8 *)&value64; + + if (address > 0xff || !value64) + return AE_BAD_PARAMETER; + + if (function != ACPI_WRITE && function != ACPI_READ) + return AE_BAD_PARAMETER; + + spin_lock_irq(&rtc_lock); + + for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value) + if (function == ACPI_READ) + *value = CMOS_READ(address); + else + CMOS_WRITE(*value, address); + + spin_unlock_irq(&rtc_lock); + + return AE_OK; +} + +static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, + const struct acpi_device_id *id) +{ + acpi_status status; + + status = acpi_install_address_space_handler(adev->handle, + ACPI_ADR_SPACE_CMOS, + &acpi_cmos_rtc_space_handler, + NULL, NULL); + if (ACPI_FAILURE(status)) { + pr_err(PREFIX "Error installing CMOS-RTC region handler\n"); + return -ENODEV; + } + + return 0; +} + +static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev) +{ + if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle, + ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler))) + pr_err(PREFIX "Error removing CMOS-RTC region handler\n"); +} + +static struct acpi_scan_handler cmos_rtc_handler = { + .ids = acpi_cmos_rtc_ids, + .attach = acpi_install_cmos_rtc_space_handler, + .detach = acpi_remove_cmos_rtc_space_handler, +}; + +void __init acpi_cmos_rtc_init(void) +{ + acpi_scan_add_handler(&cmos_rtc_handler); +} diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 297cbf456f8..4163d4ba017 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -45,6 +45,11 @@ void acpi_memory_hotplug_init(void); #else static inline void acpi_memory_hotplug_init(void) {} #endif +#ifdef CONFIG_X86 +void acpi_cmos_rtc_init(void); +#else +static inline void acpi_cmos_rtc_init(void) {} +#endif void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, const char *name); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b14ac46948c..a514be21644 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2040,6 +2040,7 @@ int __init acpi_scan_init(void) acpi_pci_link_init(); acpi_platform_init(); acpi_lpss_init(); + acpi_cmos_rtc_init(); acpi_container_init(); acpi_memory_hotplug_init(); -- cgit v1.2.3-70-g09d2 From eff9a4b62b14cf0d9913e3caf1f26f8b7a6105c9 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Jun 2013 02:27:51 +0000 Subject: ACPI / EC: Add HP Folio 13 to ec_dmi_table in order to skip DSDT scan HP Folio 13's BIOS defines CMOS RTC Operation Region and the EC's _REG method will access that region. To allow the CMOS RTC region handler to be installed before the EC _REG method is first invoked, add ec_skip_dsdt_scan() as HP Folio 13's callback to ec_dmi_table. References: https://bugzilla.kernel.org/show_bug.cgi?id=54621 Reported-and-tested-by: Stefan Nagy Signed-off-by: Lan Tianyu Cc: 3.9+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/ec.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index edc00818c80..80403c1a89f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -983,6 +983,10 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { ec_enlarge_storm_threshold, "CLEVO hardware", { DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."), DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL}, + { + ec_skip_dsdt_scan, "HP Folio 13", { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL}, {}, }; -- cgit v1.2.3-70-g09d2 From 10619066a353f27fe3700a448fa2b21643687840 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 23 May 2013 10:27:46 +0300 Subject: ACPI: implement acpi_os_get_timer() according the spec ACPI Timer() opcode should return monotonically increasing clock with 100ns granularity according the ACPI 5.0 spec. Testing the current Timer() implementation with following ASL code (and an additional debug print in acpi_os_sleep() to get the sleep times dumped out to dmesg): // Test: 10ms Store(Timer, Local1) Sleep(10) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) // Test: 200ms Store(Timer, Local1) Sleep(200) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) // Test 1300ms Store(Timer, Local1) Sleep(1300) Divide(Subtract(Timer, Local1), 10000,, Local1) Sleep(Local1) The second sleep value is calculated using Timer(). If the implementation is good enough we should be able to get the second value pretty close to the first. However, the current Timer() gives pretty bad sleep times: [ 11.488100] ACPI: acpi_os_get_timer() TBD [ 11.492150] ACPI: Sleep(10) [ 11.502993] ACPI: Sleep(0) [ 11.506315] ACPI: Sleep(200) [ 11.706237] ACPI: Sleep(0) [ 11.709550] ACPI: Sleep(1300) [ 13.008929] ACPI: Sleep(0) Fix this with the help of ktime_get(). Once the fix is applied and run against the same ASL code we get: [ 11.486786] ACPI: Sleep(10) [ 11.499029] ACPI: Sleep(12) [ 11.512350] ACPI: Sleep(200) [ 11.712282] ACPI: Sleep(200) [ 11.912170] ACPI: Sleep(1300) [ 13.211577] ACPI: Sleep(1300) That is much more closer to the values we expected. Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e72186340fe..c29076909ef 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -835,19 +835,9 @@ void acpi_os_stall(u32 us) */ u64 acpi_os_get_timer(void) { - static u64 t; - -#ifdef CONFIG_HPET - /* TBD: use HPET if available */ -#endif - -#ifdef CONFIG_X86_PM_TIMER - /* TBD: default to PM timer if HPET was not available */ -#endif - if (!t) - printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n"); - - return ++t; + u64 time_ns = ktime_to_ns(ktime_get()); + do_div(time_ns, 100); + return time_ns; } acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) -- cgit v1.2.3-70-g09d2 From 9b5c7a5a977a330ffaf83c4d383ba247c74c800f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 27 Jun 2013 14:01:02 +0200 Subject: ACPI / PM: Fix possible NULL pointer deref in acpi_pm_device_sleep_state() After commit fa1675b (ACPI / PM: Rework and clean up acpi_dev_pm_get_state()) a NULL pointer dereference will take place if NULL is passed to acpi_pm_device_sleep_state() as the second argument. Fix that by avoiding to use the pointer that may be NULL until it's necessary to store a return value at the location pointed to by it (if not NULL). Reported-and-tested-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index fd363b57a59..4c56dc830eb 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -521,7 +521,7 @@ 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; - int ret, d_max; + int ret, d_min, d_max; if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3_COLD) return -EINVAL; @@ -540,19 +540,23 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) } ret = acpi_dev_pm_get_state(dev, adev, acpi_target_system_state(), - d_min_p, &d_max); + &d_min, &d_max); if (ret) return ret; - if (d_max_in < *d_min_p) + if (d_max_in < d_min) return -EINVAL; if (d_max > d_max_in) { - for (d_max = d_max_in; d_max > *d_min_p; d_max--) { + for (d_max = d_max_in; d_max > d_min; d_max--) { if (adev->power.states[d_max].flags.valid) break; } } + + if (d_min_p) + *d_min_p = d_min; + return d_max; } EXPORT_SYMBOL(acpi_pm_device_sleep_state); -- cgit v1.2.3-70-g09d2