diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-08 17:34:51 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-08 17:34:51 -0700 |
| commit | 883a2dfd6f13eca5aab30f0bcc9a6f1e2f983b1e (patch) | |
| tree | 0e1154fe7cff7ae646bd89b1e2f6c30aaa877d13 /drivers/acpi/resource.c | |
| parent | 331c5841ddbb4cf3034ffc425a70f42acc5cdaff (diff) | |
| parent | 8076ca480f40c51ab87d8301c830a817b900b4d1 (diff) | |
Merge tag 'pm+acpi-4.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management and ACPI updates from Rafael Wysocki:
"These are fixes on top of the previous PM+ACPI pull requests
(including one fix for a 4.1 regression) and two commits adding
_CLS-based device enumeration support to the ACPI core and the ATA
subsystem that waited for the latest ACPICA changes to be merged.
Specifics:
- Fix for an ACPI resources management regression introduced during
the 4.1 cycle (that unfortunately went into -stable) effectively
reverting the bad commit along with the recent fixups on top of it
and using an alternative approach to address the underlying issue
(Rafael J Wysocki).
- Fix for a memory leak and an incorrect return value in an error
code path in the ACPI LPSS (Low-Power Subsystem) driver (Rafael J
Wysocki).
- Fix for a leftover dangling pointer in an error code path in the
new wakeup IRQ support code (Rafael J Wysocki).
- Fix to prevent infinite loops (due to errors in other places) from
happening in the core generic PM domains support code (Geert
Uytterhoeven).
- Hibernation documentation update/clarification (Uwe Geuder).
- Support for _CLS-based device enumeration in the ACPI core and in
the ATA subsystem (Suravee Suthikulpanit)"
* tag 'pm+acpi-4.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM / wakeirq: Avoid setting power.wakeirq too hastily
ata: ahci_platform: Add ACPI _CLS matching
ACPI / scan: Add support for ACPI _CLS device matching
PM / hibernate: clarify resume documentation
PM / Domains: Avoid infinite loops in attach/detach code
ACPI / LPSS: Fix up acpi_lpss_create_device()
ACPI / PNP: Reserve ACPI resources at the fs_initcall_sync stage
Diffstat (limited to 'drivers/acpi/resource.c')
| -rw-r--r-- | drivers/acpi/resource.c | 162 |
1 files changed, 0 insertions, 162 deletions
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 10561ce16ed1..8244f013f210 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -26,7 +26,6 @@ #include <linux/device.h> #include <linux/export.h> #include <linux/ioport.h> -#include <linux/list.h> #include <linux/slab.h> #ifdef CONFIG_X86 @@ -622,164 +621,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares, return (type & types) ? 0 : 1; } EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); - -struct reserved_region { - struct list_head node; - u64 start; - u64 end; -}; - -static LIST_HEAD(reserved_io_regions); -static LIST_HEAD(reserved_mem_regions); - -static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags, - char *desc) -{ - unsigned int length = end - start + 1; - struct resource *res; - - res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ? - request_region(start, length, desc) : - request_mem_region(start, length, desc); - if (!res) - return -EIO; - - res->flags &= ~flags; - return 0; -} - -static int add_region_before(u64 start, u64 end, u8 space_id, - unsigned long flags, char *desc, - struct list_head *head) -{ - struct reserved_region *reg; - int error; - - reg = kmalloc(sizeof(*reg), GFP_KERNEL); - if (!reg) - return -ENOMEM; - - error = request_range(start, end, space_id, flags, desc); - if (error) { - kfree(reg); - return error; - } - - reg->start = start; - reg->end = end; - list_add_tail(®->node, head); - return 0; -} - -/** - * acpi_reserve_region - Reserve an I/O or memory region as a system resource. - * @start: Starting address of the region. - * @length: Length of the region. - * @space_id: Identifier of address space to reserve the region from. - * @flags: Resource flags to clear for the region after requesting it. - * @desc: Region description (for messages). - * - * Reserve an I/O or memory region as a system resource to prevent others from - * using it. If the new region overlaps with one of the regions (in the given - * address space) already reserved by this routine, only the non-overlapping - * parts of it will be reserved. - * - * Returned is either 0 (success) or a negative error code indicating a resource - * reservation problem. It is the code of the first encountered error, but the - * routine doesn't abort until it has attempted to request all of the parts of - * the new region that don't overlap with other regions reserved previously. - * - * The resources requested by this routine are never released. - */ -int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, - unsigned long flags, char *desc) -{ - struct list_head *regions; - struct reserved_region *reg; - u64 end = start + length - 1; - int ret = 0, error = 0; - - if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) - regions = &reserved_io_regions; - else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) - regions = &reserved_mem_regions; - else - return -EINVAL; - - if (list_empty(regions)) - return add_region_before(start, end, space_id, flags, desc, regions); - - list_for_each_entry(reg, regions, node) - if (reg->start == end + 1) { - /* The new region can be prepended to this one. */ - ret = request_range(start, end, space_id, flags, desc); - if (!ret) - reg->start = start; - - return ret; - } else if (reg->start > end) { - /* No overlap. Add the new region here and get out. */ - return add_region_before(start, end, space_id, flags, - desc, ®->node); - } else if (reg->end == start - 1) { - goto combine; - } else if (reg->end >= start) { - goto overlap; - } - - /* The new region goes after the last existing one. */ - return add_region_before(start, end, space_id, flags, desc, regions); - - overlap: - /* - * The new region overlaps an existing one. - * - * The head part of the new region immediately preceding the existing - * overlapping one can be combined with it right away. - */ - if (reg->start > start) { - error = request_range(start, reg->start - 1, space_id, flags, desc); - if (error) - ret = error; - else - reg->start = start; - } - - combine: - /* - * The new region is adjacent to an existing one. If it extends beyond - * that region all the way to the next one, it is possible to combine - * all three of them. - */ - while (reg->end < end) { - struct reserved_region *next = NULL; - u64 a = reg->end + 1, b = end; - - if (!list_is_last(®->node, regions)) { - next = list_next_entry(reg, node); - if (next->start <= end) - b = next->start - 1; - } - error = request_range(a, b, space_id, flags, desc); - if (!error) { - if (next && next->start == b + 1) { - reg->end = next->end; - list_del(&next->node); - kfree(next); - } else { - reg->end = end; - break; - } - } else if (next) { - if (!ret) - ret = error; - - reg = next; - } else { - break; - } - } - - return ret ? ret : error; -} -EXPORT_SYMBOL_GPL(acpi_reserve_region); |
