#include <linux/device.h>
#include <linux/export.h>
#include <linux/ioport.h>
---#include <linux/list.h>
#include <linux/slab.h>
#ifdef CONFIG_X86
u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
bool wp = addr->info.mem.write_protect;
u64 len = attr->address_length;
+++ u64 start, end, offset = 0;
struct resource *res = &win->res;
/*
pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",
addr->min_address_fixed, addr->max_address_fixed, len);
--- res->start = attr->minimum;
--- res->end = attr->maximum;
---
/*
* For bridges that translate addresses across the bridge,
* translation_offset is the offset that must be added to the
* primary side. Non-bridge devices must list 0 for all Address
* Translation offset bits.
*/
--- if (addr->producer_consumer == ACPI_PRODUCER) {
--- res->start += attr->translation_offset;
--- res->end += attr->translation_offset;
--- } else if (attr->translation_offset) {
+++ if (addr->producer_consumer == ACPI_PRODUCER)
+++ offset = attr->translation_offset;
+++ else if (attr->translation_offset)
pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
attr->translation_offset);
+++ start = attr->minimum + offset;
+++ end = attr->maximum + offset;
+++
+++ win->offset = offset;
+++ res->start = start;
+++ res->end = end;
+++ if (sizeof(resource_size_t) < sizeof(u64) &&
+++ (offset != win->offset || start != res->start || end != res->end)) {
+++ pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
+++ attr->minimum, attr->maximum);
+++ return false;
}
switch (addr->resource_type) {
return false;
}
--- win->offset = attr->translation_offset;
---
if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW;
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);