During enabling ACPI based IOAPIC hotplug, Thomas noticed some issues
in ACPI resource parsing interfaces. So this is an effort to improve them.
Patch 1 refines ACPICA resource descriptors, which has already been
merged into "git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git bleeding-edge"
Patch 2-12 improve ACPI resource parsing interfaces and also fixes some
bugs.
Patch 13-20 try to share the common data structure resource_list_entry
between PCI and ACPI. It may also be shared with PNP too.
Patch 21-23 enable ACPI based IOAPIC hotplug.
The patchset is based on v3.19-rc6+ and passed Fengguang's 0day test
suite. You may get it from:
https://github.com/jiangliu/linux.git acpires_v2
V3->V4:
1) rename resource_list_entry as resource_entry to avoid conflicts
2) kill pcibios_disable_device()
3) Patch 1-16 are the same with v3
V2->V3:
1) Split out the patch to fix bug in io resource check according to Bjorn's
suggestion
2) Fix minor coding style bugs
V1->V2:
1) Refine the way to share common code between address space and extended
address space.
2) Relax some checks to avoid regressions according to Rafael's suggestions.
3) Introduce struct resource_win to avoiding add extra parameter "offset"
to several interfaces.
4) Add patches to enable ACPI based IOAPIC hotplug, which has been reviwed
several rounds.
5) Rebase to v3.19-rc6+
Jiang Liu (14):
ACPI: Fix a bug in parsing ACPI Memory24 resource
ACPI: Normalize return value of resource parser functions
ACPI: Set flag IORESOURCE_UNSET for unassigned resources
ACPI: Enforce stricter checks for address space descriptors
ACPI: Return translation offset when parsing ACPI address space
resources
ACPI: Translate resource into master side address for bridge window
resources
ACPI: Add field offset to struct resource_list_entry
ACPI: Introduce helper function acpi_dev_filter_resource_type()
resources: Move struct resource_list_entry from ACPI into resource
core
PCI: Use common resource list management code instead of private
implementation
x86/PCI: Fix the range check for IO resources
x86/PCI/ACPI: Use common ACPI resource interfaces to simplify
implementation
x86/PCI: Refine the way to release PCI IRQ resources
x86/irq, ACPI: Implement ACPI driver to support IOAPIC hotplug
Lv Zheng (1):
ACPICA: Resources: Provide common part for struct
acpi_resource_address structures.
Thomas Gleixner (7):
ACPI: Remove redundant check in function
acpi_dev_resource_address_space()
ACPI: Implement proper length checks for mem resources
ACPI: Use the length check for io resources as well
ACPI: Let the parser return false for disabled resources
ACPI: Unify the parsing of address_space and ext_address_space
ACPI: Move the window flag logic to the combined parser
ACPI: Add prefetch decoding to the address space parser
Yinghai Lu (1):
ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug
arch/arm/kernel/bios32.c | 5 +-
arch/ia64/kernel/acpi-ext.c | 6 +-
arch/ia64/pci/pci.c | 14 +-
arch/x86/include/asm/pci_x86.h | 2 -
arch/x86/pci/acpi.c | 293 +++++++++--------------------
arch/x86/pci/bus_numa.c | 4 +-
arch/x86/pci/common.c | 34 +++-
arch/x86/pci/intel_mid_pci.c | 4 +-
arch/x86/pci/irq.c | 15 +-
arch/x86/pci/mmconfig-shared.c | 6 +-
drivers/acpi/Kconfig | 6 +
drivers/acpi/Makefile | 1 +
drivers/acpi/acpi_lpss.c | 8 +-
drivers/acpi/acpi_memhotplug.c | 8 +-
drivers/acpi/acpi_platform.c | 4 +-
drivers/acpi/acpica/rsaddr.c | 9 +-
drivers/acpi/acpica/rsdumpinfo.c | 59 +++---
drivers/acpi/acpica/rsxface.c | 10 +-
drivers/acpi/internal.h | 7 +
drivers/acpi/ioapic.c | 229 +++++++++++++++++++++++
drivers/acpi/pci_irq.c | 9 +-
drivers/acpi/pci_root.c | 9 +-
drivers/acpi/processor_core.c | 123 +++++++++++-
drivers/acpi/resource.c | 353 +++++++++++++++++++++--------------
drivers/char/hpet.c | 4 +-
drivers/dma/acpi-dma.c | 10 +-
drivers/hv/vmbus_drv.c | 4 +-
drivers/pci/bus.c | 18 +-
drivers/pci/host-bridge.c | 8 +-
drivers/pci/host/pci-host-generic.c | 4 +-
drivers/pci/host/pci-xgene.c | 4 +-
drivers/pci/host/pcie-xilinx.c | 4 +-
drivers/pci/probe.c | 10 +-
drivers/pnp/pnpacpi/rsparser.c | 45 ++---
drivers/xen/xen-acpi-memhotplug.c | 8 +-
include/acpi/acrestyp.h | 40 ++--
include/linux/acpi.h | 22 ++-
include/linux/pci.h | 9 +-
include/linux/resource_ext.h | 77 ++++++++
kernel/resource.c | 25 +++
40 files changed, 970 insertions(+), 540 deletions(-)
create mode 100644 drivers/acpi/ioapic.c
create mode 100644 include/linux/resource_ext.h
--
1.7.10.4
From: Lv Zheng <[email protected]>
struct acpi_resource_address and struct acpi_resource_extended_address64 share substracts
just at different offsets. To unify the parsing functions, OSPMs like Linux
need a new ACPI_ADDRESS64_ATTRIBUTE as their substructs, so they can
extract the shared data.
This patch also synchronizes the structure changes to the Linux kernel.
The usages are searched by matching the following keywords:
1. acpi_resource_address
2. acpi_resource_extended_address
3. ACPI_RESOURCE_TYPE_ADDRESS
4. ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS
And we found and fixed the usages in the following files:
arch/ia64/kernel/acpi-ext.c
arch/ia64/pci/pci.c
arch/x86/pci/acpi.c
arch/x86/pci/mmconfig-shared.c
drivers/xen/xen-acpi-memhotplug.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/pci_root.c
drivers/acpi/resource.c
drivers/char/hpet.c
drivers/pnp/pnpacpi/rsparser.c
drivers/hv/vmbus_drv.c
Build tests are passed with defconfig/allnoconfig/allyesconfig and
defconfig+CONFIG_ACPI=n.
Original-by: Thomas Gleixner <[email protected]>
Original-by: Jiang Liu <[email protected]>
Signed-off-by: Lv Zheng <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
arch/ia64/kernel/acpi-ext.c | 6 ++--
arch/ia64/pci/pci.c | 14 ++++-----
arch/x86/pci/acpi.c | 26 ++++++++--------
arch/x86/pci/mmconfig-shared.c | 6 ++--
drivers/acpi/acpi_memhotplug.c | 8 ++---
drivers/acpi/acpica/rsaddr.c | 9 +++---
drivers/acpi/acpica/rsdumpinfo.c | 59 +++++++++++++++++++------------------
drivers/acpi/acpica/rsxface.c | 10 +++----
drivers/acpi/pci_root.c | 6 ++--
drivers/acpi/resource.c | 24 +++++++--------
drivers/char/hpet.c | 4 +--
drivers/hv/vmbus_drv.c | 4 +--
drivers/pnp/pnpacpi/rsparser.c | 16 +++++-----
drivers/xen/xen-acpi-memhotplug.c | 8 ++---
include/acpi/acrestyp.h | 40 +++++++++++++++----------
15 files changed, 125 insertions(+), 115 deletions(-)
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 8b9318d311a0..bd09bf74f187 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -69,10 +69,10 @@ static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
status = acpi_resource_to_address64(resource, &addr);
if (ACPI_SUCCESS(status) &&
addr.resource_type == ACPI_MEMORY_RANGE &&
- addr.address_length &&
+ addr.address.address_length &&
addr.producer_consumer == ACPI_CONSUMER) {
- space->base = addr.minimum;
- space->length = addr.address_length;
+ space->base = addr.address.minimum;
+ space->length = addr.address.address_length;
return AE_CTRL_TERMINATE;
}
return AE_OK; /* keep looking */
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 900cc93e5409..48cc65705db4 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -188,12 +188,12 @@ static u64 add_io_space(struct pci_root_info *info,
name = (char *)(iospace + 1);
- min = addr->minimum;
- max = min + addr->address_length - 1;
+ min = addr->address.minimum;
+ max = min + addr->address.address_length - 1;
if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION)
sparse = 1;
- space_nr = new_space(addr->translation_offset, sparse);
+ space_nr = new_space(addr->address.translation_offset, sparse);
if (space_nr == ~0)
goto free_resource;
@@ -247,7 +247,7 @@ static acpi_status resource_to_window(struct acpi_resource *resource,
if (ACPI_SUCCESS(status) &&
(addr->resource_type == ACPI_MEMORY_RANGE ||
addr->resource_type == ACPI_IO_RANGE) &&
- addr->address_length &&
+ addr->address.address_length &&
addr->producer_consumer == ACPI_PRODUCER)
return AE_OK;
@@ -284,7 +284,7 @@ static acpi_status add_window(struct acpi_resource *res, void *data)
if (addr.resource_type == ACPI_MEMORY_RANGE) {
flags = IORESOURCE_MEM;
root = &iomem_resource;
- offset = addr.translation_offset;
+ offset = addr.address.translation_offset;
} else if (addr.resource_type == ACPI_IO_RANGE) {
flags = IORESOURCE_IO;
root = &ioport_resource;
@@ -297,8 +297,8 @@ static acpi_status add_window(struct acpi_resource *res, void *data)
resource = &info->res[info->res_num];
resource->name = info->name;
resource->flags = flags;
- resource->start = addr.minimum + offset;
- resource->end = resource->start + addr.address_length - 1;
+ resource->start = addr.address.minimum + offset;
+ resource->end = resource->start + addr.address.address_length - 1;
info->res_offset[info->res_num] = offset;
if (insert_resource(root, resource)) {
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index cfd1b132b8e3..bb98afd0591e 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -231,23 +231,23 @@ static acpi_status resource_to_addr(struct acpi_resource *resource,
case ACPI_RESOURCE_TYPE_MEMORY24:
memory24 = &resource->data.memory24;
addr->resource_type = ACPI_MEMORY_RANGE;
- addr->minimum = memory24->minimum;
- addr->address_length = memory24->address_length;
- addr->maximum = addr->minimum + addr->address_length - 1;
+ addr->address.minimum = memory24->minimum;
+ addr->address.address_length = memory24->address_length;
+ addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
return AE_OK;
case ACPI_RESOURCE_TYPE_MEMORY32:
memory32 = &resource->data.memory32;
addr->resource_type = ACPI_MEMORY_RANGE;
- addr->minimum = memory32->minimum;
- addr->address_length = memory32->address_length;
- addr->maximum = addr->minimum + addr->address_length - 1;
+ addr->address.minimum = memory32->minimum;
+ addr->address.address_length = memory32->address_length;
+ addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
return AE_OK;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
fixed_memory32 = &resource->data.fixed_memory32;
addr->resource_type = ACPI_MEMORY_RANGE;
- addr->minimum = fixed_memory32->address;
- addr->address_length = fixed_memory32->address_length;
- addr->maximum = addr->minimum + addr->address_length - 1;
+ addr->address.minimum = fixed_memory32->address;
+ addr->address.address_length = fixed_memory32->address_length;
+ addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
return AE_OK;
case ACPI_RESOURCE_TYPE_ADDRESS16:
case ACPI_RESOURCE_TYPE_ADDRESS32:
@@ -256,7 +256,7 @@ static acpi_status resource_to_addr(struct acpi_resource *resource,
if (ACPI_SUCCESS(status) &&
(addr->resource_type == ACPI_MEMORY_RANGE ||
addr->resource_type == ACPI_IO_RANGE) &&
- addr->address_length > 0) {
+ addr->address.address_length > 0) {
return AE_OK;
}
break;
@@ -298,8 +298,8 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
} else
return AE_OK;
- start = addr.minimum + addr.translation_offset;
- orig_end = end = addr.maximum + addr.translation_offset;
+ start = addr.address.minimum + addr.address.translation_offset;
+ orig_end = end = addr.address.maximum + addr.address.translation_offset;
/* Exclude non-addressable range or non-addressable portion of range */
end = min(end, (u64)iomem_resource.end);
@@ -320,7 +320,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
res->flags = flags;
res->start = start;
res->end = end;
- info->res_offset[info->res_num] = addr.translation_offset;
+ info->res_offset[info->res_num] = addr.address.translation_offset;
info->res_num++;
if (!pci_use_crs)
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 326198a4434e..5a8dceac3094 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -397,12 +397,12 @@ static acpi_status check_mcfg_resource(struct acpi_resource *res, void *data)
status = acpi_resource_to_address64(res, &address);
if (ACPI_FAILURE(status) ||
- (address.address_length <= 0) ||
+ (address.address.address_length <= 0) ||
(address.resource_type != ACPI_MEMORY_RANGE))
return AE_OK;
- if ((mcfg_res->start >= address.minimum) &&
- (mcfg_res->end < (address.minimum + address.address_length))) {
+ if ((mcfg_res->start >= address.address.minimum) &&
+ (mcfg_res->end < (address.address.minimum + address.address.address_length))) {
mcfg_res->flags = 1;
return AE_CTRL_TERMINATE;
}
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 23e2319ead41..ee28f4d15625 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -101,8 +101,8 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
/* Can we combine the resource range information? */
if ((info->caching == address64.info.mem.caching) &&
(info->write_protect == address64.info.mem.write_protect) &&
- (info->start_addr + info->length == address64.minimum)) {
- info->length += address64.address_length;
+ (info->start_addr + info->length == address64.address.minimum)) {
+ info->length += address64.address.address_length;
return AE_OK;
}
}
@@ -114,8 +114,8 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
INIT_LIST_HEAD(&new->list);
new->caching = address64.info.mem.caching;
new->write_protect = address64.info.mem.write_protect;
- new->start_addr = address64.minimum;
- new->length = address64.address_length;
+ new->start_addr = address64.address.minimum;
+ new->length = address64.address.address_length;
list_add_tail(&new->list, &mem_device->res_list);
return AE_OK;
diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c
index 916fd095ff34..94a3a057042c 100644
--- a/drivers/acpi/acpica/rsaddr.c
+++ b/drivers/acpi/acpica/rsaddr.c
@@ -74,7 +74,7 @@ struct acpi_rsconvert_info acpi_rs_convert_address16[5] = {
* Address Translation Offset
* Address Length
*/
- {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity),
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.address.granularity),
AML_OFFSET(address16.granularity),
5},
@@ -112,7 +112,7 @@ struct acpi_rsconvert_info acpi_rs_convert_address32[5] = {
* Address Translation Offset
* Address Length
*/
- {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity),
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.address.granularity),
AML_OFFSET(address32.granularity),
5},
@@ -150,7 +150,7 @@ struct acpi_rsconvert_info acpi_rs_convert_address64[5] = {
* Address Translation Offset
* Address Length
*/
- {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity),
+ {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.address.granularity),
AML_OFFSET(address64.granularity),
5},
@@ -194,7 +194,8 @@ struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = {
* Address Length
* Type-Specific Attribute
*/
- {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.ext_address64.granularity),
+ {ACPI_RSC_MOVE64,
+ ACPI_RS_OFFSET(data.ext_address64.address.granularity),
AML_OFFSET(ext_address64.granularity),
6}
};
diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c
index 2f9332d5c973..6ba7ad5faa9c 100644
--- a/drivers/acpi/acpica/rsdumpinfo.c
+++ b/drivers/acpi/acpica/rsdumpinfo.c
@@ -183,15 +183,15 @@ struct acpi_rsdump_info acpi_rs_dump_address16[8] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16),
"16-Bit WORD Address Space", NULL},
{ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity), "Granularity",
- NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum), "Address Minimum",
- NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum), "Address Maximum",
- NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.translation_offset),
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address.granularity),
+ "Granularity", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address.minimum),
+ "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address.maximum),
+ "Address Maximum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address.translation_offset),
"Translation Offset", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length),
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address.address_length),
"Address Length", NULL},
{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL}
};
@@ -200,15 +200,15 @@ struct acpi_rsdump_info acpi_rs_dump_address32[8] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32),
"32-Bit DWORD Address Space", NULL},
{ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity), "Granularity",
- NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum), "Address Minimum",
- NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum), "Address Maximum",
- NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.translation_offset),
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address.granularity),
+ "Granularity", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address.minimum),
+ "Address Minimum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address.maximum),
+ "Address Maximum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address.translation_offset),
"Translation Offset", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length),
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address.address_length),
"Address Length", NULL},
{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL}
};
@@ -217,15 +217,15 @@ struct acpi_rsdump_info acpi_rs_dump_address64[8] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64),
"64-Bit QWORD Address Space", NULL},
{ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity), "Granularity",
- NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum), "Address Minimum",
- NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum), "Address Maximum",
- NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.translation_offset),
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address.granularity),
+ "Granularity", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address.minimum),
+ "Address Minimum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address.maximum),
+ "Address Maximum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address.translation_offset),
"Translation Offset", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length),
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address.address_length),
"Address Length", NULL},
{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL}
};
@@ -234,15 +234,16 @@ struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = {
{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64),
"64-Bit Extended Address Space", NULL},
{ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity),
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address.granularity),
"Granularity", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum),
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address.minimum),
"Address Minimum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum),
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address.maximum),
"Address Maximum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.translation_offset),
+ {ACPI_RSD_UINT64,
+ ACPI_RSD_OFFSET(ext_address64.address.translation_offset),
"Translation Offset", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address_length),
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.address.address_length),
"Address Length", NULL},
{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.type_specific),
"Type-Specific Attribute", NULL}
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index 877ab9202133..295287891174 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -60,11 +60,11 @@ ACPI_MODULE_NAME("rsxface")
ACPI_COPY_FIELD(out, in, min_address_fixed); \
ACPI_COPY_FIELD(out, in, max_address_fixed); \
ACPI_COPY_FIELD(out, in, info); \
- ACPI_COPY_FIELD(out, in, granularity); \
- ACPI_COPY_FIELD(out, in, minimum); \
- ACPI_COPY_FIELD(out, in, maximum); \
- ACPI_COPY_FIELD(out, in, translation_offset); \
- ACPI_COPY_FIELD(out, in, address_length); \
+ ACPI_COPY_FIELD(out, in, address.granularity); \
+ ACPI_COPY_FIELD(out, in, address.minimum); \
+ ACPI_COPY_FIELD(out, in, address.maximum); \
+ ACPI_COPY_FIELD(out, in, address.translation_offset); \
+ ACPI_COPY_FIELD(out, in, address.address_length); \
ACPI_COPY_FIELD(out, in, resource_source);
/* Local prototypes */
static acpi_status
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index c6bcb8c719d8..e53e0f659204 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -112,10 +112,10 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
if (ACPI_FAILURE(status))
return AE_OK;
- if ((address.address_length > 0) &&
+ if ((address.address.address_length > 0) &&
(address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
- res->start = address.minimum;
- res->end = address.minimum + address.address_length - 1;
+ res->start = address.address.minimum;
+ res->end = address.address.minimum + address.address.address_length - 1;
}
return AE_OK;
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 782a0d15c25f..d0a4d90c6bcc 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -202,22 +202,22 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
if (ACPI_FAILURE(status))
return false;
- res->start = addr.minimum;
- res->end = addr.maximum;
+ res->start = addr.address.minimum;
+ res->end = addr.address.maximum;
window = addr.producer_consumer == ACPI_PRODUCER;
switch(addr.resource_type) {
case ACPI_MEMORY_RANGE:
- len = addr.maximum - addr.minimum + 1;
+ len = addr.address.maximum - addr.address.minimum + 1;
res->flags = acpi_dev_memresource_flags(len,
addr.info.mem.write_protect,
window);
break;
case ACPI_IO_RANGE:
- io_decode = addr.granularity == 0xfff ?
+ io_decode = addr.address.granularity == 0xfff ?
ACPI_DECODE_10 : ACPI_DECODE_16;
- res->flags = acpi_dev_ioresource_flags(addr.minimum,
- addr.maximum,
+ res->flags = acpi_dev_ioresource_flags(addr.address.minimum,
+ addr.address.maximum,
io_decode, window);
break;
case ACPI_BUS_NUMBER_RANGE:
@@ -253,22 +253,22 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
ext_addr = &ares->data.ext_address64;
- res->start = ext_addr->minimum;
- res->end = ext_addr->maximum;
+ res->start = ext_addr->address.minimum;
+ res->end = ext_addr->address.maximum;
window = ext_addr->producer_consumer == ACPI_PRODUCER;
switch(ext_addr->resource_type) {
case ACPI_MEMORY_RANGE:
- len = ext_addr->maximum - ext_addr->minimum + 1;
+ len = ext_addr->address.maximum - ext_addr->address.minimum + 1;
res->flags = acpi_dev_memresource_flags(len,
ext_addr->info.mem.write_protect,
window);
break;
case ACPI_IO_RANGE:
- io_decode = ext_addr->granularity == 0xfff ?
+ io_decode = ext_addr->address.granularity == 0xfff ?
ACPI_DECODE_10 : ACPI_DECODE_16;
- res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
- ext_addr->maximum,
+ res->flags = acpi_dev_ioresource_flags(ext_addr->address.minimum,
+ ext_addr->address.maximum,
io_decode, window);
break;
case ACPI_BUS_NUMBER_RANGE:
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index d5d4cd82b9f7..5c0baa9ffc64 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -976,8 +976,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
status = acpi_resource_to_address64(res, &addr);
if (ACPI_SUCCESS(status)) {
- hdp->hd_phys_address = addr.minimum;
- hdp->hd_address = ioremap(addr.minimum, addr.address_length);
+ hdp->hd_phys_address = addr.address.minimum;
+ hdp->hd_address = ioremap(addr.address.minimum, addr.address.address_length);
if (hpet_is_known(hdp)) {
iounmap(hdp->hd_address);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 4d6b26979fbd..bb3725b672cf 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -861,8 +861,8 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
break;
case ACPI_RESOURCE_TYPE_ADDRESS64:
- hyperv_mmio.start = res->data.address64.minimum;
- hyperv_mmio.end = res->data.address64.maximum;
+ hyperv_mmio.start = res->data.address64.address.minimum;
+ hyperv_mmio.end = res->data.address64.address.maximum;
break;
}
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 66977ebf13b3..2d9bc789af0f 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -410,12 +410,12 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
- pnp_register_mem_resource(dev, option_flags, p->minimum,
- p->minimum, 0, p->address_length,
+ pnp_register_mem_resource(dev, option_flags, p->address.minimum,
+ p->address.minimum, 0, p->address.address_length,
flags);
} else if (p->resource_type == ACPI_IO_RANGE)
- pnp_register_port_resource(dev, option_flags, p->minimum,
- p->minimum, 0, p->address_length,
+ pnp_register_port_resource(dev, option_flags, p->address.minimum,
+ p->address.minimum, 0, p->address.address_length,
IORESOURCE_IO_FIXED);
}
@@ -429,12 +429,12 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
if (p->resource_type == ACPI_MEMORY_RANGE) {
if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
flags = IORESOURCE_MEM_WRITEABLE;
- pnp_register_mem_resource(dev, option_flags, p->minimum,
- p->minimum, 0, p->address_length,
+ pnp_register_mem_resource(dev, option_flags, p->address.minimum,
+ p->address.minimum, 0, p->address.address_length,
flags);
} else if (p->resource_type == ACPI_IO_RANGE)
- pnp_register_port_resource(dev, option_flags, p->minimum,
- p->minimum, 0, p->address_length,
+ pnp_register_port_resource(dev, option_flags, p->address.minimum,
+ p->address.minimum, 0, p->address.address_length,
IORESOURCE_IO_FIXED);
}
diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c
index 34e40b733f9a..4fc886cd5586 100644
--- a/drivers/xen/xen-acpi-memhotplug.c
+++ b/drivers/xen/xen-acpi-memhotplug.c
@@ -117,8 +117,8 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
list_for_each_entry(info, &mem_device->res_list, list) {
if ((info->caching == address64.info.mem.caching) &&
(info->write_protect == address64.info.mem.write_protect) &&
- (info->start_addr + info->length == address64.minimum)) {
- info->length += address64.address_length;
+ (info->start_addr + info->length == address64.address.minimum)) {
+ info->length += address64.address.address_length;
return AE_OK;
}
}
@@ -130,8 +130,8 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
INIT_LIST_HEAD(&new->list);
new->caching = address64.info.mem.caching;
new->write_protect = address64.info.mem.write_protect;
- new->start_addr = address64.minimum;
- new->length = address64.address_length;
+ new->start_addr = address64.address.minimum;
+ new->length = address64.address.address_length;
list_add_tail(&new->list, &mem_device->res_list);
return AE_OK;
diff --git a/include/acpi/acrestyp.h b/include/acpi/acrestyp.h
index eb760ca0b2e0..0b75e01212c7 100644
--- a/include/acpi/acrestyp.h
+++ b/include/acpi/acrestyp.h
@@ -305,43 +305,51 @@ struct acpi_resource_source {
u8 max_address_fixed; \
union acpi_resource_attribute info;
-struct acpi_resource_address {
-ACPI_RESOURCE_ADDRESS_COMMON};
-
-struct acpi_resource_address16 {
- ACPI_RESOURCE_ADDRESS_COMMON u16 granularity;
+struct acpi_address16_attribute {
+ u16 granularity;
u16 minimum;
u16 maximum;
u16 translation_offset;
u16 address_length;
- struct acpi_resource_source resource_source;
};
-struct acpi_resource_address32 {
- ACPI_RESOURCE_ADDRESS_COMMON u32 granularity;
+struct acpi_address32_attribute {
+ u32 granularity;
u32 minimum;
u32 maximum;
u32 translation_offset;
u32 address_length;
- struct acpi_resource_source resource_source;
};
-struct acpi_resource_address64 {
- ACPI_RESOURCE_ADDRESS_COMMON u64 granularity;
+struct acpi_address64_attribute {
+ u64 granularity;
u64 minimum;
u64 maximum;
u64 translation_offset;
u64 address_length;
+};
+
+struct acpi_resource_address {
+ACPI_RESOURCE_ADDRESS_COMMON};
+
+struct acpi_resource_address16 {
+ ACPI_RESOURCE_ADDRESS_COMMON struct acpi_address16_attribute address;
+ struct acpi_resource_source resource_source;
+};
+
+struct acpi_resource_address32 {
+ ACPI_RESOURCE_ADDRESS_COMMON struct acpi_address32_attribute address;
+ struct acpi_resource_source resource_source;
+};
+
+struct acpi_resource_address64 {
+ ACPI_RESOURCE_ADDRESS_COMMON struct acpi_address64_attribute address;
struct acpi_resource_source resource_source;
};
struct acpi_resource_extended_address64 {
ACPI_RESOURCE_ADDRESS_COMMON u8 revision_ID;
- u64 granularity;
- u64 minimum;
- u64 maximum;
- u64 translation_offset;
- u64 address_length;
+ struct acpi_address64_attribute address;
u64 type_specific;
};
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
The ACPI type is checked in acpi_resource_to_address64() anyway.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index d0a4d90c6bcc..1c616a56e007 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -189,15 +189,6 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
u64 len;
u8 io_decode;
- switch (ares->type) {
- case ACPI_RESOURCE_TYPE_ADDRESS16:
- case ACPI_RESOURCE_TYPE_ADDRESS32:
- case ACPI_RESOURCE_TYPE_ADDRESS64:
- break;
- default:
- return false;
- }
-
status = acpi_resource_to_address64(ares, &addr);
if (ACPI_FAILURE(status))
return false;
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
Check whether the resulting length is the same as the given
length. Check for start <= end as well.
We need to hand in the resource for this, so we can apply the flags
directly.
[Jiang] Remove enforcement that resource starting address must be
non-zero.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 62 ++++++++++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 27 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 1c616a56e007..3e7d9f6eb875 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -34,21 +34,37 @@
#define valid_IRQ(i) (true)
#endif
-static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
- bool window)
+static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
{
- unsigned long flags = IORESOURCE_MEM;
+ u64 reslen = end - start + 1;
- if (len == 0)
- flags |= IORESOURCE_DISABLED;
+ /*
+ * CHECKME: len might be required to check versus a minimum
+ * length as well. 1 for io is fine, but for memory it does
+ * not make any sense at all.
+ */
+ if (len && reslen && reslen == len && start <= end)
+ return true;
+
+ pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
+ io ? "io" : "mem", start, end, len);
+
+ return false;
+}
+
+static void acpi_dev_memresource_flags(struct resource *res, u64 len,
+ u8 write_protect, bool window)
+{
+ res->flags = IORESOURCE_MEM;
+
+ if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
+ res->flags |= IORESOURCE_DISABLED;
if (write_protect == ACPI_READ_WRITE_MEMORY)
- flags |= IORESOURCE_MEM_WRITEABLE;
+ res->flags |= IORESOURCE_MEM_WRITEABLE;
if (window)
- flags |= IORESOURCE_WINDOW;
-
- return flags;
+ res->flags |= IORESOURCE_WINDOW;
}
static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
@@ -56,7 +72,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
{
res->start = start;
res->end = start + len - 1;
- res->flags = acpi_dev_memresource_flags(len, write_protect, false);
+ acpi_dev_memresource_flags(res, len, write_protect, false);
}
/**
@@ -77,24 +93,18 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
switch (ares->type) {
case ACPI_RESOURCE_TYPE_MEMORY24:
memory24 = &ares->data.memory24;
- if (!memory24->minimum && !memory24->address_length)
- return false;
acpi_dev_get_memresource(res, memory24->minimum,
memory24->address_length,
memory24->write_protect);
break;
case ACPI_RESOURCE_TYPE_MEMORY32:
memory32 = &ares->data.memory32;
- if (!memory32->minimum && !memory32->address_length)
- return false;
acpi_dev_get_memresource(res, memory32->minimum,
memory32->address_length,
memory32->write_protect);
break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
fixed_memory32 = &ares->data.fixed_memory32;
- if (!fixed_memory32->address && !fixed_memory32->address_length)
- return false;
acpi_dev_get_memresource(res, fixed_memory32->address,
fixed_memory32->address_length,
fixed_memory32->write_protect);
@@ -102,7 +112,8 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
default:
return false;
}
- return true;
+
+ return !(res->flags & IORESOURCE_DISABLED);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
@@ -186,7 +197,6 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
acpi_status status;
struct acpi_resource_address64 addr;
bool window;
- u64 len;
u8 io_decode;
status = acpi_resource_to_address64(ares, &addr);
@@ -199,10 +209,9 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
switch(addr.resource_type) {
case ACPI_MEMORY_RANGE:
- len = addr.address.maximum - addr.address.minimum + 1;
- res->flags = acpi_dev_memresource_flags(len,
- addr.info.mem.write_protect,
- window);
+ acpi_dev_memresource_flags(res, addr.address.address_length,
+ addr.info.mem.write_protect,
+ window);
break;
case ACPI_IO_RANGE:
io_decode = addr.address.granularity == 0xfff ?
@@ -236,7 +245,6 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
{
struct acpi_resource_extended_address64 *ext_addr;
bool window;
- u64 len;
u8 io_decode;
if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
@@ -250,10 +258,10 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
switch(ext_addr->resource_type) {
case ACPI_MEMORY_RANGE:
- len = ext_addr->address.maximum - ext_addr->address.minimum + 1;
- res->flags = acpi_dev_memresource_flags(len,
- ext_addr->info.mem.write_protect,
- window);
+ acpi_dev_memresource_flags(res,
+ ext_addr->address.address_length,
+ ext_addr->info.mem.write_protect,
+ window);
break;
case ACPI_IO_RANGE:
io_decode = ext_addr->address.granularity == 0xfff ?
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
Also apply length check to IO resources.
[Jiang] Remove enforcement that resource starting address must be
non-zero.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 44 +++++++++++++++++++-------------------------
1 file changed, 19 insertions(+), 25 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 3e7d9f6eb875..16d291c60277 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -117,31 +117,30 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
-static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode,
- bool window)
+static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
+ u8 io_decode, bool window)
{
- int flags = IORESOURCE_IO;
+ res->flags = IORESOURCE_IO;
- if (io_decode == ACPI_DECODE_16)
- flags |= IORESOURCE_IO_16BIT_ADDR;
+ if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
+ res->flags |= IORESOURCE_DISABLED;
- if (start > end || end >= 0x10003)
- flags |= IORESOURCE_DISABLED;
+ if (res->end >= 0x10003)
+ res->flags |= IORESOURCE_DISABLED;
- if (window)
- flags |= IORESOURCE_WINDOW;
+ if (io_decode == ACPI_DECODE_16)
+ res->flags |= IORESOURCE_IO_16BIT_ADDR;
- return flags;
+ if (window)
+ res->flags |= IORESOURCE_WINDOW;
}
static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
u8 io_decode)
{
- u64 end = start + len - 1;
-
res->start = start;
- res->end = end;
- res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false);
+ res->end = start + len - 1;
+ acpi_dev_ioresource_flags(res, len, io_decode, false);
}
/**
@@ -161,16 +160,12 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
switch (ares->type) {
case ACPI_RESOURCE_TYPE_IO:
io = &ares->data.io;
- if (!io->minimum && !io->address_length)
- return false;
acpi_dev_get_ioresource(res, io->minimum,
io->address_length,
io->io_decode);
break;
case ACPI_RESOURCE_TYPE_FIXED_IO:
fixed_io = &ares->data.fixed_io;
- if (!fixed_io->address && !fixed_io->address_length)
- return false;
acpi_dev_get_ioresource(res, fixed_io->address,
fixed_io->address_length,
ACPI_DECODE_10);
@@ -178,7 +173,8 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
default:
return false;
}
- return true;
+
+ return !(res->flags & IORESOURCE_DISABLED);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
@@ -216,9 +212,8 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
case ACPI_IO_RANGE:
io_decode = addr.address.granularity == 0xfff ?
ACPI_DECODE_10 : ACPI_DECODE_16;
- res->flags = acpi_dev_ioresource_flags(addr.address.minimum,
- addr.address.maximum,
- io_decode, window);
+ acpi_dev_ioresource_flags(res, addr.address.address_length,
+ io_decode, window);
break;
case ACPI_BUS_NUMBER_RANGE:
res->flags = IORESOURCE_BUS;
@@ -266,9 +261,8 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
case ACPI_IO_RANGE:
io_decode = ext_addr->address.granularity == 0xfff ?
ACPI_DECODE_10 : ACPI_DECODE_16;
- res->flags = acpi_dev_ioresource_flags(ext_addr->address.minimum,
- ext_addr->address.maximum,
- io_decode, window);
+ acpi_dev_ioresource_flags(res, ext_addr->address.address_length,
+ io_decode, window);
break;
case ACPI_BUS_NUMBER_RANGE:
res->flags = IORESOURCE_BUS;
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
If the parser disables a resource during parsing, let it return false,
so the calling code does not need to implement further checks.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 16d291c60277..cdb1a3c4a0b9 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -219,10 +219,10 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
res->flags = IORESOURCE_BUS;
break;
default:
- res->flags = 0;
+ return false;
}
- return true;
+ return !(res->flags & IORESOURCE_DISABLED);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
@@ -268,10 +268,10 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
res->flags = IORESOURCE_BUS;
break;
default:
- res->flags = 0;
+ return false;
}
- return true;
+ return !(res->flags & IORESOURCE_DISABLED);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
With the unions in place which let us identify the substructs we can
use a single parser for address_space and ext_address_space.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 90 ++++++++++++++++++-----------------------------
1 file changed, 34 insertions(+), 56 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index cdb1a3c4a0b9..99903d196024 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -178,6 +178,35 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
+static bool acpi_decode_space(struct resource *res,
+ struct acpi_resource_address *addr,
+ struct acpi_address64_attribute *attr)
+{
+ u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
+ bool window = addr->producer_consumer == ACPI_PRODUCER;
+ bool wp = addr->info.mem.write_protect;
+ u64 len = attr->address_length;
+
+ res->start = attr->minimum;
+ res->end = attr->maximum;
+
+ switch (addr->resource_type) {
+ case ACPI_MEMORY_RANGE:
+ acpi_dev_memresource_flags(res, len, wp, window);
+ break;
+ case ACPI_IO_RANGE:
+ acpi_dev_ioresource_flags(res, len, iodec, window);
+ break;
+ case ACPI_BUS_NUMBER_RANGE:
+ res->flags = IORESOURCE_BUS;
+ break;
+ default:
+ return false;
+ }
+
+ return !(res->flags & IORESOURCE_DISABLED);
+}
+
/**
* acpi_dev_resource_address_space - Extract ACPI address space information.
* @ares: Input ACPI resource object.
@@ -190,39 +219,13 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
bool acpi_dev_resource_address_space(struct acpi_resource *ares,
struct resource *res)
{
- acpi_status status;
struct acpi_resource_address64 addr;
- bool window;
- u8 io_decode;
-
- status = acpi_resource_to_address64(ares, &addr);
- if (ACPI_FAILURE(status))
- return false;
- res->start = addr.address.minimum;
- res->end = addr.address.maximum;
- window = addr.producer_consumer == ACPI_PRODUCER;
-
- switch(addr.resource_type) {
- case ACPI_MEMORY_RANGE:
- acpi_dev_memresource_flags(res, addr.address.address_length,
- addr.info.mem.write_protect,
- window);
- break;
- case ACPI_IO_RANGE:
- io_decode = addr.address.granularity == 0xfff ?
- ACPI_DECODE_10 : ACPI_DECODE_16;
- acpi_dev_ioresource_flags(res, addr.address.address_length,
- io_decode, window);
- break;
- case ACPI_BUS_NUMBER_RANGE:
- res->flags = IORESOURCE_BUS;
- break;
- default:
+ if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
return false;
- }
- return !(res->flags & IORESOURCE_DISABLED);
+ return acpi_decode_space(res, (struct acpi_resource_address *)&addr,
+ &addr.address);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
@@ -239,39 +242,14 @@ bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
struct resource *res)
{
struct acpi_resource_extended_address64 *ext_addr;
- bool window;
- u8 io_decode;
if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
return false;
ext_addr = &ares->data.ext_address64;
- res->start = ext_addr->address.minimum;
- res->end = ext_addr->address.maximum;
- window = ext_addr->producer_consumer == ACPI_PRODUCER;
-
- switch(ext_addr->resource_type) {
- case ACPI_MEMORY_RANGE:
- acpi_dev_memresource_flags(res,
- ext_addr->address.address_length,
- ext_addr->info.mem.write_protect,
- window);
- break;
- case ACPI_IO_RANGE:
- io_decode = ext_addr->address.granularity == 0xfff ?
- ACPI_DECODE_10 : ACPI_DECODE_16;
- acpi_dev_ioresource_flags(res, ext_addr->address.address_length,
- io_decode, window);
- break;
- case ACPI_BUS_NUMBER_RANGE:
- res->flags = IORESOURCE_BUS;
- break;
- default:
- return false;
- }
-
- return !(res->flags & IORESOURCE_DISABLED);
+ return acpi_decode_space(res, (struct acpi_resource_address *)ext_addr,
+ &ext_addr->address);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
Normal memory and io resources have window always set to false. Move
the flag logic to the unified address space parser.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 99903d196024..15d17937c431 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -53,7 +53,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
}
static void acpi_dev_memresource_flags(struct resource *res, u64 len,
- u8 write_protect, bool window)
+ u8 write_protect)
{
res->flags = IORESOURCE_MEM;
@@ -62,9 +62,6 @@ static void acpi_dev_memresource_flags(struct resource *res, u64 len,
if (write_protect == ACPI_READ_WRITE_MEMORY)
res->flags |= IORESOURCE_MEM_WRITEABLE;
-
- if (window)
- res->flags |= IORESOURCE_WINDOW;
}
static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
@@ -72,7 +69,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
{
res->start = start;
res->end = start + len - 1;
- acpi_dev_memresource_flags(res, len, write_protect, false);
+ acpi_dev_memresource_flags(res, len, write_protect);
}
/**
@@ -118,7 +115,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
- u8 io_decode, bool window)
+ u8 io_decode)
{
res->flags = IORESOURCE_IO;
@@ -130,9 +127,6 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
if (io_decode == ACPI_DECODE_16)
res->flags |= IORESOURCE_IO_16BIT_ADDR;
-
- if (window)
- res->flags |= IORESOURCE_WINDOW;
}
static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
@@ -140,7 +134,7 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
{
res->start = start;
res->end = start + len - 1;
- acpi_dev_ioresource_flags(res, len, io_decode, false);
+ acpi_dev_ioresource_flags(res, len, io_decode);
}
/**
@@ -183,7 +177,6 @@ static bool acpi_decode_space(struct resource *res,
struct acpi_address64_attribute *attr)
{
u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
- bool window = addr->producer_consumer == ACPI_PRODUCER;
bool wp = addr->info.mem.write_protect;
u64 len = attr->address_length;
@@ -192,10 +185,10 @@ static bool acpi_decode_space(struct resource *res,
switch (addr->resource_type) {
case ACPI_MEMORY_RANGE:
- acpi_dev_memresource_flags(res, len, wp, window);
+ acpi_dev_memresource_flags(res, len, wp);
break;
case ACPI_IO_RANGE:
- acpi_dev_ioresource_flags(res, len, iodec, window);
+ acpi_dev_ioresource_flags(res, len, iodec);
break;
case ACPI_BUS_NUMBER_RANGE:
res->flags = IORESOURCE_BUS;
@@ -204,6 +197,9 @@ static bool acpi_decode_space(struct resource *res,
return false;
}
+ if (addr->producer_consumer == ACPI_PRODUCER)
+ res->flags |= IORESOURCE_WINDOW;
+
return !(res->flags & IORESOURCE_DISABLED);
}
--
1.7.10.4
From: Thomas Gleixner <[email protected]>
Add support of PREFETCH attributre to ACPI address space and extended
address space parser.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 15d17937c431..7ce00a63f695 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -200,6 +200,9 @@ static bool acpi_decode_space(struct resource *res,
if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW;
+ if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+ res->flags |= IORESOURCE_PREFETCH;
+
return !(res->flags & IORESOURCE_DISABLED);
}
--
1.7.10.4
According to ACPI spec 5, section 6.4.3.1 "24-Bit Memory Range Descriptor",
minimum, maximum and address_length field in struct acpi_resource_memory24
is in granularity of 256-bytes. So shift 8-bit left to get correct address.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 7ce00a63f695..5544c6d26f32 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -90,8 +90,8 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
switch (ares->type) {
case ACPI_RESOURCE_TYPE_MEMORY24:
memory24 = &ares->data.memory24;
- acpi_dev_get_memresource(res, memory24->minimum,
- memory24->address_length,
+ acpi_dev_get_memresource(res, memory24->minimum << 8,
+ memory24->address_length << 8,
memory24->write_protect);
break;
case ACPI_RESOURCE_TYPE_MEMORY32:
--
1.7.10.4
Normalize return value of resource parse functions as:
1) return "true" if resource is assigned.
2) return "false" and IORESOURCE_DISABLED setting in res->flags if
resource is unassigned.
3) return "false" and zeroing res->flags if it's not an valid or
expected resource.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 5544c6d26f32..32561290a4a0 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -80,6 +80,11 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
* Check if the given ACPI resource object represents a memory resource and
* if that's the case, use the information in it to populate the generic
* resource object pointed to by @res.
+ *
+ * Return:
+ * 1) false with res->flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 3) true: valid assigned resource
*/
bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
{
@@ -107,6 +112,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
fixed_memory32->write_protect);
break;
default:
+ res->flags = 0;
return false;
}
@@ -145,6 +151,11 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
* Check if the given ACPI resource object represents an I/O resource and
* if that's the case, use the information in it to populate the generic
* resource object pointed to by @res.
+ *
+ * Return:
+ * 1) false with res->flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 3) true: valid assigned resource
*/
bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
{
@@ -165,6 +176,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
ACPI_DECODE_10);
break;
default:
+ res->flags = 0;
return false;
}
@@ -214,12 +226,18 @@ static bool acpi_decode_space(struct resource *res,
* Check if the given ACPI resource object represents an address space resource
* and if that's the case, use the information in it to populate the generic
* resource object pointed to by @res.
+ *
+ * Return:
+ * 1) false with res->flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 3) true: valid assigned resource
*/
bool acpi_dev_resource_address_space(struct acpi_resource *ares,
struct resource *res)
{
struct acpi_resource_address64 addr;
+ res->flags = 0;
if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
return false;
@@ -236,12 +254,18 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
* Check if the given ACPI resource object represents an extended address space
* resource and if that's the case, use the information in it to populate the
* generic resource object pointed to by @res.
+ *
+ * Return:
+ * 1) false with res->flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 3) true: valid assigned resource
*/
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
struct resource *res)
{
struct acpi_resource_extended_address64 *ext_addr;
+ res->flags = 0;
if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
return false;
@@ -339,6 +363,11 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
* represented by the resource and populate the generic resource object pointed
* to by @res accordingly. If the registration of the GSI is not successful,
* IORESOURCE_DISABLED will be set it that object's flags.
+ *
+ * Return:
+ * 1) false with res->flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 3) true: valid assigned resource
*/
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
struct resource *res)
@@ -372,6 +401,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
ext_irq->sharable, false);
break;
default:
+ res->flags = 0;
return false;
}
--
1.7.10.4
Also set flag IORESOURCE_UNSET for unassigned resource in addition to
IORESOURCE_DISABLED to mark resource as unassigned.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 32561290a4a0..5bf73a9f26d9 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -58,7 +58,7 @@ static void acpi_dev_memresource_flags(struct resource *res, u64 len,
res->flags = IORESOURCE_MEM;
if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))
- res->flags |= IORESOURCE_DISABLED;
+ res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
if (write_protect == ACPI_READ_WRITE_MEMORY)
res->flags |= IORESOURCE_MEM_WRITEABLE;
@@ -126,10 +126,10 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
res->flags = IORESOURCE_IO;
if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
- res->flags |= IORESOURCE_DISABLED;
+ res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
if (res->end >= 0x10003)
- res->flags |= IORESOURCE_DISABLED;
+ res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
if (io_decode == ACPI_DECODE_16)
res->flags |= IORESOURCE_IO_16BIT_ADDR;
@@ -304,7 +304,7 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
{
res->start = gsi;
res->end = gsi;
- res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED;
+ res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET;
}
static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
--
1.7.10.4
Enforce stricter checks for address space descriptors according to
ACPI spec.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 5bf73a9f26d9..57891a621b96 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -192,6 +192,15 @@ static bool acpi_decode_space(struct resource *res,
bool wp = addr->info.mem.write_protect;
u64 len = attr->address_length;
+ /*
+ * Filter out invalid descriptor according to ACPI Spec 5.0, section
+ * 6.4.3.5 Address Space Resource Descriptors.
+ */
+ if ((addr->min_address_fixed != addr->max_address_fixed && len) ||
+ (addr->min_address_fixed && addr->max_address_fixed && !len))
+ 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;
--
1.7.10.4
Change function acpi_dev_resource_address_space() and
acpi_dev_resource_ext_address_space() to return address space
translation offset.
It's based on a patch from Yinghai Lu <[email protected]>.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 58 ++++++++++++++++++++++------------------
drivers/pnp/pnpacpi/rsparser.c | 29 ++++++++++----------
include/linux/acpi.h | 9 +++++--
3 files changed, 54 insertions(+), 42 deletions(-)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 57891a621b96..c902c8eece81 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -184,13 +184,14 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
-static bool acpi_decode_space(struct resource *res,
+static bool acpi_decode_space(struct resource_win *win,
struct acpi_resource_address *addr,
struct acpi_address64_attribute *attr)
{
u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
bool wp = addr->info.mem.write_protect;
u64 len = attr->address_length;
+ struct resource *res = &win->res;
/*
* Filter out invalid descriptor according to ACPI Spec 5.0, section
@@ -218,6 +219,8 @@ static bool acpi_decode_space(struct resource *res,
return false;
}
+ win->offset = attr->translation_offset;
+
if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW;
@@ -230,27 +233,28 @@ static bool acpi_decode_space(struct resource *res,
/**
* acpi_dev_resource_address_space - Extract ACPI address space information.
* @ares: Input ACPI resource object.
- * @res: Output generic resource object.
+ * @win: Output generic resource object.
*
* Check if the given ACPI resource object represents an address space resource
* and if that's the case, use the information in it to populate the generic
- * resource object pointed to by @res.
+ * resource object pointed to by @win.
*
* Return:
- * 1) false with res->flags setting to zero: not the expected resource type
- * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 1) false with win->res.flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
+ * resource
* 3) true: valid assigned resource
*/
bool acpi_dev_resource_address_space(struct acpi_resource *ares,
- struct resource *res)
+ struct resource_win *win)
{
struct acpi_resource_address64 addr;
- res->flags = 0;
+ win->res.flags = 0;
if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))
return false;
- return acpi_decode_space(res, (struct acpi_resource_address *)&addr,
+ return acpi_decode_space(win, (struct acpi_resource_address *)&addr,
&addr.address);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
@@ -258,29 +262,30 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
/**
* acpi_dev_resource_ext_address_space - Extract ACPI address space information.
* @ares: Input ACPI resource object.
- * @res: Output generic resource object.
+ * @win: Output generic resource object.
*
* Check if the given ACPI resource object represents an extended address space
* resource and if that's the case, use the information in it to populate the
- * generic resource object pointed to by @res.
+ * generic resource object pointed to by @win.
*
* Return:
- * 1) false with res->flags setting to zero: not the expected resource type
- * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource
+ * 1) false with win->res.flags setting to zero: not the expected resource type
+ * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned
+ * resource
* 3) true: valid assigned resource
*/
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
- struct resource *res)
+ struct resource_win *win)
{
struct acpi_resource_extended_address64 *ext_addr;
- res->flags = 0;
+ win->res.flags = 0;
if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
return false;
ext_addr = &ares->data.ext_address64;
- return acpi_decode_space(res, (struct acpi_resource_address *)ext_addr,
+ return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr,
&ext_addr->address);
}
EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
@@ -441,7 +446,7 @@ struct res_proc_context {
int error;
};
-static acpi_status acpi_dev_new_resource_entry(struct resource *r,
+static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
struct res_proc_context *c)
{
struct resource_list_entry *rentry;
@@ -451,7 +456,7 @@ static acpi_status acpi_dev_new_resource_entry(struct resource *r,
c->error = -ENOMEM;
return AE_NO_MEMORY;
}
- rentry->res = *r;
+ rentry->res = win->res;
list_add_tail(&rentry->node, c->list);
c->count++;
return AE_OK;
@@ -461,7 +466,8 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
void *context)
{
struct res_proc_context *c = context;
- struct resource r;
+ struct resource_win win;
+ struct resource *res = &win.res;
int i;
if (c->preproc) {
@@ -476,18 +482,18 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
}
}
- memset(&r, 0, sizeof(r));
+ memset(&win, 0, sizeof(win));
- if (acpi_dev_resource_memory(ares, &r)
- || acpi_dev_resource_io(ares, &r)
- || acpi_dev_resource_address_space(ares, &r)
- || acpi_dev_resource_ext_address_space(ares, &r))
- return acpi_dev_new_resource_entry(&r, c);
+ if (acpi_dev_resource_memory(ares, res)
+ || acpi_dev_resource_io(ares, res)
+ || acpi_dev_resource_address_space(ares, &win)
+ || acpi_dev_resource_ext_address_space(ares, &win))
+ return acpi_dev_new_resource_entry(&win, c);
- for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) {
+ for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) {
acpi_status status;
- status = acpi_dev_new_resource_entry(&r, c);
+ status = acpi_dev_new_resource_entry(&win, c);
if (ACPI_FAILURE(status))
return status;
}
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 2d9bc789af0f..ff0356fb378f 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -180,20 +180,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
struct pnp_dev *dev = data;
struct acpi_resource_dma *dma;
struct acpi_resource_vendor_typed *vendor_typed;
- struct resource r = {0};
+ struct resource_win win = {{0}, 0};
+ struct resource *r = &win.res;
int i, flags;
- if (acpi_dev_resource_address_space(res, &r)
- || acpi_dev_resource_ext_address_space(res, &r)) {
- pnp_add_resource(dev, &r);
+ if (acpi_dev_resource_address_space(res, &win)
+ || acpi_dev_resource_ext_address_space(res, &win)) {
+ pnp_add_resource(dev, &win.res);
return AE_OK;
}
- r.flags = 0;
- if (acpi_dev_resource_interrupt(res, 0, &r)) {
- pnpacpi_add_irqresource(dev, &r);
- for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
- pnpacpi_add_irqresource(dev, &r);
+ r->flags = 0;
+ if (acpi_dev_resource_interrupt(res, 0, r)) {
+ pnpacpi_add_irqresource(dev, r);
+ for (i = 1; acpi_dev_resource_interrupt(res, i, r); i++)
+ pnpacpi_add_irqresource(dev, r);
if (i > 1) {
/*
@@ -209,7 +210,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
}
}
return AE_OK;
- } else if (r.flags & IORESOURCE_DISABLED) {
+ } else if (r->flags & IORESOURCE_DISABLED) {
pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
return AE_OK;
}
@@ -218,13 +219,13 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_MEMORY24:
case ACPI_RESOURCE_TYPE_MEMORY32:
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
- if (acpi_dev_resource_memory(res, &r))
- pnp_add_resource(dev, &r);
+ if (acpi_dev_resource_memory(res, r))
+ pnp_add_resource(dev, r);
break;
case ACPI_RESOURCE_TYPE_IO:
case ACPI_RESOURCE_TYPE_FIXED_IO:
- if (acpi_dev_resource_io(res, &r))
- pnp_add_resource(dev, &r);
+ if (acpi_dev_resource_io(res, r))
+ pnp_add_resource(dev, r);
break;
case ACPI_RESOURCE_TYPE_DMA:
dma = &res->data.dma;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d459cd17b477..be9eaee8f4ae 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -285,12 +285,17 @@ extern int pnpacpi_disabled;
#define PXM_INVAL (-1)
+struct resource_win {
+ struct resource res;
+ resource_size_t offset;
+};
+
bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);
bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);
bool acpi_dev_resource_address_space(struct acpi_resource *ares,
- struct resource *res);
+ struct resource_win *win);
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
- struct resource *res);
+ struct resource_win *win);
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
struct resource *res);
--
1.7.10.4
Add translation_offset into the result address for bridge window
resources to form the master side address.
Currently acpi_dev_resource_{ext_}address_space() are only used for
devices instead of bridges, so it won't break current users. Later
it will be used to support PCI host bridge drivers.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index c902c8eece81..4dc8cfb2e94e 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -205,6 +205,21 @@ static bool acpi_decode_space(struct resource_win *win,
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
+ * address on the secondary side to obtain the address on 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) {
+ pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
+ attr->translation_offset);
+ }
+
switch (addr->resource_type) {
case ACPI_MEMORY_RANGE:
acpi_dev_memresource_flags(res, len, wp);
--
1.7.10.4
Add field offset to struct resource_list_entry to host address space
translation offset so it could be used to represent bridge resources.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 1 +
include/linux/acpi.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 4dc8cfb2e94e..1c3abae6f2fa 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -472,6 +472,7 @@ static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
return AE_NO_MEMORY;
}
rentry->res = win->res;
+ rentry->offset = win->offset;
list_add_tail(&rentry->node, c->list);
c->count++;
return AE_OK;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index be9eaee8f4ae..21dac3cb62d2 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -303,6 +303,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
struct resource_list_entry {
struct list_head node;
struct resource res;
+ resource_size_t offset;
};
void acpi_dev_free_resource_list(struct list_head *list);
--
1.7.10.4
Introduce helper function acpi_dev_filter_resource_type(), which may
be used by acpi_dev_get_resources() to filer out resource based on
resource type.
Signed-off-by: Jiang Liu <[email protected]>
---
drivers/acpi/resource.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 8 +++++++
2 files changed, 63 insertions(+)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 1c3abae6f2fa..3ea0d17eb951 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -569,3 +569,58 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
return c.count;
}
EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
+
+/**
+ * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
+ * types
+ * @ares: Input ACPI resource object.
+ * @types: Valid resource types of IORESOURCE_XXX
+ *
+ * This is a hepler function to support acpi_dev_get_resources(), which filters
+ * ACPI resource objects according to resource types.
+ */
+int acpi_dev_filter_resource_type(struct acpi_resource *ares,
+ unsigned long types)
+{
+ unsigned long type = 0;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ type = IORESOURCE_MEM;
+ break;
+ case ACPI_RESOURCE_TYPE_IO:
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+ type = IORESOURCE_IO;
+ break;
+ case ACPI_RESOURCE_TYPE_IRQ:
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ type = IORESOURCE_IRQ;
+ break;
+ case ACPI_RESOURCE_TYPE_DMA:
+ case ACPI_RESOURCE_TYPE_FIXED_DMA:
+ type = IORESOURCE_DMA;
+ break;
+ case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
+ type = IORESOURCE_REG;
+ break;
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+ if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)
+ type = IORESOURCE_MEM;
+ else if (ares->data.address.resource_type == ACPI_IO_RANGE)
+ type = IORESOURCE_IO;
+ else if (ares->data.address.resource_type ==
+ ACPI_BUS_NUMBER_RANGE)
+ type = IORESOURCE_BUS;
+ break;
+ default:
+ break;
+ }
+
+ return (type & types) ? 0 : 1;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 21dac3cb62d2..e818decb631f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -310,6 +310,14 @@ void acpi_dev_free_resource_list(struct list_head *list);
int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
int (*preproc)(struct acpi_resource *, void *),
void *preproc_data);
+int acpi_dev_filter_resource_type(struct acpi_resource *ares,
+ unsigned long types);
+
+static inline int acpi_dev_filter_resource_type_cb(struct acpi_resource *ares,
+ void *arg)
+{
+ return acpi_dev_filter_resource_type(ares, (unsigned long)arg);
+}
int acpi_check_resource_conflict(const struct resource *res);
--
1.7.10.4
Currently ACPI, PCI and pnp all implement the same resource list
management with different data structure. We need to transfer from
one data structure into another when passing resources from one
subsystem into another subsystem. So move struct resource_list_entry
from ACPI into resource core and rename it as resource_entry,
then it could be reused by different subystems and avoid the data
structure conversion.
Introduce dedicated header file resource_ext.h instead of embedding
it into ioport.h to avoid header file inclusion order issues.
Signed-off-by: Jiang Liu <[email protected]>
Acked-by: Vinod Koul <[email protected]>
---
drivers/acpi/acpi_lpss.c | 8 ++---
drivers/acpi/acpi_platform.c | 4 +--
drivers/acpi/resource.c | 17 ++++------
drivers/dma/acpi-dma.c | 10 +++---
include/linux/acpi.h | 12 +------
include/linux/resource_ext.h | 77 ++++++++++++++++++++++++++++++++++++++++++
kernel/resource.c | 25 ++++++++++++++
7 files changed, 120 insertions(+), 33 deletions(-)
create mode 100644 include/linux/resource_ext.h
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 4f3febf8a589..dfd1b8095dad 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -313,7 +313,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
{
struct lpss_device_desc *dev_desc;
struct lpss_private_data *pdata;
- struct resource_list_entry *rentry;
+ struct resource_entry *rentry;
struct list_head resource_list;
struct platform_device *pdev;
int ret;
@@ -333,12 +333,12 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
goto err_out;
list_for_each_entry(rentry, &resource_list, node)
- if (resource_type(&rentry->res) == IORESOURCE_MEM) {
+ if (resource_type(rentry->res) == IORESOURCE_MEM) {
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 = resource_size(rentry->res);
+ pdata->mmio_base = ioremap(rentry->res->start,
pdata->mmio_size);
break;
}
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 6ba8beb6b9d2..1284138e42ab 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -45,7 +45,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
struct platform_device *pdev = NULL;
struct acpi_device *acpi_parent;
struct platform_device_info pdevinfo;
- struct resource_list_entry *rentry;
+ struct resource_entry *rentry;
struct list_head resource_list;
struct resource *resources = NULL;
int count;
@@ -71,7 +71,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
}
count = 0;
list_for_each_entry(rentry, &resource_list, node)
- resources[count++] = rentry->res;
+ resources[count++] = *rentry->res;
acpi_dev_free_resource_list(&resource_list);
}
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 3ea0d17eb951..4752b9939987 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -444,12 +444,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
*/
void acpi_dev_free_resource_list(struct list_head *list)
{
- struct resource_list_entry *rentry, *re;
-
- list_for_each_entry_safe(rentry, re, list, node) {
- list_del(&rentry->node);
- kfree(rentry);
- }
+ resource_list_free(list);
}
EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
@@ -464,16 +459,16 @@ struct res_proc_context {
static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
struct res_proc_context *c)
{
- struct resource_list_entry *rentry;
+ struct resource_entry *rentry;
- rentry = kmalloc(sizeof(*rentry), GFP_KERNEL);
+ rentry = resource_list_create_entry(NULL, 0);
if (!rentry) {
c->error = -ENOMEM;
return AE_NO_MEMORY;
}
- rentry->res = win->res;
+ *rentry->res = win->res;
rentry->offset = win->offset;
- list_add_tail(&rentry->node, c->list);
+ resource_list_add_tail(rentry, c->list);
c->count++;
return AE_OK;
}
@@ -534,7 +529,7 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
* returned as the final error code.
*
* The resultant struct resource objects are put on the list pointed to by
- * @list, that must be empty initially, as members of struct resource_list_entry
+ * @list, that must be empty initially, as members of struct resource_entry
* objects. Callers of this routine should use %acpi_dev_free_resource_list() to
* free that list.
*
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index de361a156b34..5a635646e05c 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -43,7 +43,7 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
{
const struct acpi_csrt_shared_info *si;
struct list_head resource_list;
- struct resource_list_entry *rentry;
+ struct resource_entry *rentry;
resource_size_t mem = 0, irq = 0;
int ret;
@@ -56,10 +56,10 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
return 0;
list_for_each_entry(rentry, &resource_list, node) {
- if (resource_type(&rentry->res) == IORESOURCE_MEM)
- mem = rentry->res.start;
- else if (resource_type(&rentry->res) == IORESOURCE_IRQ)
- irq = rentry->res.start;
+ if (resource_type(rentry->res) == IORESOURCE_MEM)
+ mem = rentry->res->start;
+ else if (resource_type(rentry->res) == IORESOURCE_IRQ)
+ irq = rentry->res->start;
}
acpi_dev_free_resource_list(&resource_list);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index e818decb631f..e53822148b6a 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -27,6 +27,7 @@
#include <linux/errno.h>
#include <linux/ioport.h> /* for struct resource */
+#include <linux/resource_ext.h>
#include <linux/device.h>
#include <linux/property.h>
@@ -285,11 +286,6 @@ extern int pnpacpi_disabled;
#define PXM_INVAL (-1)
-struct resource_win {
- struct resource res;
- resource_size_t offset;
-};
-
bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);
bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);
bool acpi_dev_resource_address_space(struct acpi_resource *ares,
@@ -300,12 +296,6 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
struct resource *res);
-struct resource_list_entry {
- struct list_head node;
- struct resource res;
- resource_size_t offset;
-};
-
void acpi_dev_free_resource_list(struct list_head *list);
int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
int (*preproc)(struct acpi_resource *, void *),
diff --git a/include/linux/resource_ext.h b/include/linux/resource_ext.h
new file mode 100644
index 000000000000..e2bf63d881d4
--- /dev/null
+++ b/include/linux/resource_ext.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015, Intel Corporation
+ * Author: Jiang Liu <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+#ifndef _LINUX_RESOURCE_EXT_H
+#define _LINUX_RESOURCE_EXT_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+/* Represent resource window for bridge devices */
+struct resource_win {
+ struct resource res; /* In master (CPU) address space */
+ resource_size_t offset; /* Translation offset for bridge */
+};
+
+/*
+ * Common resource list management data structure and interfaces to support
+ * ACPI, PNP and PCI host bridge etc.
+ */
+struct resource_entry {
+ struct list_head node;
+ struct resource *res; /* In master (CPU) address space */
+ resource_size_t offset; /* Translation offset for bridge */
+ struct resource __res; /* Default storage for res */
+};
+
+extern struct resource_entry *
+resource_list_create_entry(struct resource *res, size_t extra_size);
+extern void resource_list_free(struct list_head *head);
+
+static inline void resource_list_add(struct resource_entry *entry,
+ struct list_head *head)
+{
+ list_add(&entry->node, head);
+}
+
+static inline void resource_list_add_tail(struct resource_entry *entry,
+ struct list_head *head)
+{
+ list_add_tail(&entry->node, head);
+}
+
+static inline void resource_list_del(struct resource_entry *entry)
+{
+ list_del(&entry->node);
+}
+
+static inline void resource_list_free_entry(struct resource_entry *entry)
+{
+ kfree(entry);
+}
+
+static inline void
+resource_list_destroy_entry(struct resource_entry *entry)
+{
+ resource_list_del(entry);
+ resource_list_free_entry(entry);
+}
+
+#define resource_list_for_each_entry(entry, list) \
+ list_for_each_entry((entry), (list), node)
+
+#define resource_list_for_each_entry_safe(entry, tmp, list) \
+ list_for_each_entry_safe((entry), (tmp), (list), node)
+
+#endif /* _LINUX_RESOURCE_EXT_H */
diff --git a/kernel/resource.c b/kernel/resource.c
index 0bcebffc4e77..19f2357dfda3 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/pfn.h>
#include <linux/mm.h>
+#include <linux/resource_ext.h>
#include <asm/io.h>
@@ -1529,6 +1530,30 @@ int iomem_is_exclusive(u64 addr)
return err;
}
+struct resource_entry *resource_list_create_entry(struct resource *res,
+ size_t extra_size)
+{
+ struct resource_entry *entry;
+
+ entry = kzalloc(sizeof(*entry) + extra_size, GFP_KERNEL);
+ if (entry) {
+ INIT_LIST_HEAD(&entry->node);
+ entry->res = res ? res : &entry->__res;
+ }
+
+ return entry;
+}
+EXPORT_SYMBOL(resource_list_create_entry);
+
+void resource_list_free(struct list_head *head)
+{
+ struct resource_entry *entry, *tmp;
+
+ list_for_each_entry_safe(entry, tmp, head, node)
+ resource_list_destroy_entry(entry);
+}
+EXPORT_SYMBOL(resource_list_free);
+
static int __init strict_iomem(char *str)
{
if (strstr(str, "relaxed"))
--
1.7.10.4
Use common resource list management data structure and interfaces
instead of private implementation.
Signed-off-by: Jiang Liu <[email protected]>
Acked-by: Will Deacon <[email protected]>
Acked-by: Bjorn Helgaas <[email protected]>
---
arch/arm/kernel/bios32.c | 5 ++---
arch/x86/pci/bus_numa.c | 4 ++--
drivers/pci/bus.c | 18 ++++++------------
drivers/pci/host-bridge.c | 8 ++++----
drivers/pci/host/pci-host-generic.c | 4 ++--
drivers/pci/host/pci-xgene.c | 4 ++--
drivers/pci/host/pcie-xilinx.c | 4 ++--
drivers/pci/probe.c | 10 +++++-----
include/linux/pci.h | 9 ++-------
9 files changed, 27 insertions(+), 39 deletions(-)
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index a4effd6d8f2f..016991792b0b 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -422,17 +422,16 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
{
int ret;
- struct pci_host_bridge_window *window;
+ struct resource_entry *window;
if (list_empty(&sys->resources)) {
pci_add_resource_offset(&sys->resources,
&iomem_resource, sys->mem_offset);
}
- list_for_each_entry(window, &sys->resources, list) {
+ resource_list_for_each_entry(window, &sys->resources)
if (resource_type(window->res) == IORESOURCE_IO)
return 0;
- }
sys->io_res.start = (busnr * SZ_64K) ? : pcibios_min_io;
sys->io_res.end = (busnr + 1) * SZ_64K - 1;
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index f3a2cfc14125..7bcf06a7cd12 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -31,7 +31,7 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
{
struct pci_root_info *info = x86_find_pci_root_info(bus);
struct pci_root_res *root_res;
- struct pci_host_bridge_window *window;
+ struct resource_entry *window;
bool found = false;
if (!info)
@@ -41,7 +41,7 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
bus);
/* already added by acpi ? */
- list_for_each_entry(window, resources, list)
+ resource_list_for_each_entry(window, resources)
if (window->res->flags & IORESOURCE_BUS) {
found = true;
break;
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 8fb16188cd82..90fa3a78fb7c 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -20,17 +20,16 @@
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
resource_size_t offset)
{
- struct pci_host_bridge_window *window;
+ struct resource_entry *entry;
- window = kzalloc(sizeof(struct pci_host_bridge_window), GFP_KERNEL);
- if (!window) {
+ entry = resource_list_create_entry(res, 0);
+ if (!entry) {
printk(KERN_ERR "PCI: can't add host bridge window %pR\n", res);
return;
}
- window->res = res;
- window->offset = offset;
- list_add_tail(&window->list, resources);
+ entry->offset = offset;
+ resource_list_add_tail(entry, resources);
}
EXPORT_SYMBOL(pci_add_resource_offset);
@@ -42,12 +41,7 @@ EXPORT_SYMBOL(pci_add_resource);
void pci_free_resource_list(struct list_head *resources)
{
- struct pci_host_bridge_window *window, *tmp;
-
- list_for_each_entry_safe(window, tmp, resources, list) {
- list_del(&window->list);
- kfree(window);
- }
+ resource_list_free(resources);
}
EXPORT_SYMBOL(pci_free_resource_list);
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 0e5f3c95af5b..39b2dbe585aa 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -35,10 +35,10 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
struct resource *res)
{
struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
- struct pci_host_bridge_window *window;
+ struct resource_entry *window;
resource_size_t offset = 0;
- list_for_each_entry(window, &bridge->windows, list) {
+ resource_list_for_each_entry(window, &bridge->windows) {
if (resource_contains(window->res, res)) {
offset = window->offset;
break;
@@ -60,10 +60,10 @@ void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
struct pci_bus_region *region)
{
struct pci_host_bridge *bridge = find_pci_host_bridge(bus);
- struct pci_host_bridge_window *window;
+ struct resource_entry *window;
resource_size_t offset = 0;
- list_for_each_entry(window, &bridge->windows, list) {
+ resource_list_for_each_entry(window, &bridge->windows) {
struct pci_bus_region bus_region;
if (resource_type(res) != resource_type(window->res))
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 6eb1aa75bd37..aee3c620ecf9 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -149,14 +149,14 @@ static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
struct device *dev = pci->host.dev.parent;
struct device_node *np = dev->of_node;
resource_size_t iobase;
- struct pci_host_bridge_window *win;
+ struct resource_entry *win;
err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
&iobase);
if (err)
return err;
- list_for_each_entry(win, &pci->resources, list) {
+ resource_list_for_each_entry(win, &pci->resources) {
struct resource *parent, *res = win->res;
switch (resource_type(res)) {
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index b1d0596457c5..a704257bab7f 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -401,11 +401,11 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
struct list_head *res,
resource_size_t io_base)
{
- struct pci_host_bridge_window *window;
+ struct resource_entry *window;
struct device *dev = port->dev;
int ret;
- list_for_each_entry(window, res, list) {
+ resource_list_for_each_entry(window, res) {
struct resource *res = window->res;
u64 restype = resource_type(res);
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
index ef3ebaf9a738..601261df7663 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -737,7 +737,7 @@ static int xilinx_pcie_parse_and_add_res(struct xilinx_pcie_port *port)
resource_size_t offset;
struct of_pci_range_parser parser;
struct of_pci_range range;
- struct pci_host_bridge_window *win;
+ struct resource_entry *win;
int err = 0, mem_resno = 0;
/* Get the ranges */
@@ -807,7 +807,7 @@ static int xilinx_pcie_parse_and_add_res(struct xilinx_pcie_port *port)
free_resources:
release_child_resources(&iomem_resource);
- list_for_each_entry(win, &port->resources, list)
+ resource_list_for_each_entry(win, &port->resources)
devm_kfree(dev, win->res);
pci_free_resource_list(&port->resources);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 23212f8ae09b..8d2f400e96cb 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1895,7 +1895,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int error;
struct pci_host_bridge *bridge;
struct pci_bus *b, *b2;
- struct pci_host_bridge_window *window, *n;
+ struct resource_entry *window, *n;
struct resource *res;
resource_size_t offset;
char bus_addr[64];
@@ -1959,8 +1959,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
/* Add initial resources to the bus */
- list_for_each_entry_safe(window, n, resources, list) {
- list_move_tail(&window->list, &bridge->windows);
+ resource_list_for_each_entry_safe(window, n, resources) {
+ list_move_tail(&window->node, &bridge->windows);
res = window->res;
offset = window->offset;
if (res->flags & IORESOURCE_BUS)
@@ -2060,12 +2060,12 @@ void pci_bus_release_busn_res(struct pci_bus *b)
struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
- struct pci_host_bridge_window *window;
+ struct resource_entry *window;
bool found = false;
struct pci_bus *b;
int max;
- list_for_each_entry(window, resources, list)
+ resource_list_for_each_entry(window, resources)
if (window->res->flags & IORESOURCE_BUS) {
found = true;
break;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9603094ed59b..faa60fa26314 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -29,6 +29,7 @@
#include <linux/atomic.h>
#include <linux/device.h>
#include <linux/io.h>
+#include <linux/resource_ext.h>
#include <uapi/linux/pci.h>
#include <linux/pci_ids.h>
@@ -397,16 +398,10 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
return (pdev->error_state != pci_channel_io_normal);
}
-struct pci_host_bridge_window {
- struct list_head list;
- struct resource *res; /* host bridge aperture (CPU address) */
- resource_size_t offset; /* bus address + offset = CPU address */
-};
-
struct pci_host_bridge {
struct device dev;
struct pci_bus *bus; /* root bus */
- struct list_head windows; /* pci_host_bridge_windows */
+ struct list_head windows; /* resource_entry */
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
};
--
1.7.10.4
The range check in setup_res() checks the IO range against
iomem_resource. That's just wrong.
Reworked based on Thomas original patch.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/pci/acpi.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index bb98afd0591e..1d725d99963d 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -283,7 +283,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
struct acpi_resource_address64 addr;
acpi_status status;
unsigned long flags;
- u64 start, orig_end, end;
+ u64 start, orig_end, end, res_end;
status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
@@ -293,8 +293,10 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
flags = IORESOURCE_MEM;
if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
flags |= IORESOURCE_PREFETCH;
+ res_end = (u64)iomem_resource.end;
} else if (addr.resource_type == ACPI_IO_RANGE) {
flags = IORESOURCE_IO;
+ res_end = (u64)ioport_resource.end;
} else
return AE_OK;
@@ -302,7 +304,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
orig_end = end = addr.address.maximum + addr.address.translation_offset;
/* Exclude non-addressable range or non-addressable portion of range */
- end = min(end, (u64)iomem_resource.end);
+ end = min(end, res_end);
if (end <= start) {
dev_info(&info->bridge->dev,
"host bridge window [%#llx-%#llx] "
--
1.7.10.4
Use common ACPI resource discovery interfaces to simplify PCI host bridge
resource enumeration.
Signed-off-by: Jiang Liu <[email protected]>
Acked-by: Bjorn Helgaas <[email protected]>
---
arch/x86/pci/acpi.c | 295 ++++++++++++++++-----------------------------------
1 file changed, 91 insertions(+), 204 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 1d725d99963d..6ac273832f28 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -10,9 +10,6 @@
struct pci_root_info {
struct acpi_device *bridge;
char name[16];
- unsigned int res_num;
- struct resource *res;
- resource_size_t *res_offset;
struct pci_sysdata sd;
#ifdef CONFIG_PCI_MMCONFIG
bool mcfg_added;
@@ -218,132 +215,41 @@ static void teardown_mcfg_map(struct pci_root_info *info)
}
#endif
-static acpi_status resource_to_addr(struct acpi_resource *resource,
- struct acpi_resource_address64 *addr)
-{
- acpi_status status;
- struct acpi_resource_memory24 *memory24;
- struct acpi_resource_memory32 *memory32;
- struct acpi_resource_fixed_memory32 *fixed_memory32;
-
- memset(addr, 0, sizeof(*addr));
- switch (resource->type) {
- case ACPI_RESOURCE_TYPE_MEMORY24:
- memory24 = &resource->data.memory24;
- addr->resource_type = ACPI_MEMORY_RANGE;
- addr->address.minimum = memory24->minimum;
- addr->address.address_length = memory24->address_length;
- addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
- return AE_OK;
- case ACPI_RESOURCE_TYPE_MEMORY32:
- memory32 = &resource->data.memory32;
- addr->resource_type = ACPI_MEMORY_RANGE;
- addr->address.minimum = memory32->minimum;
- addr->address.address_length = memory32->address_length;
- addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
- return AE_OK;
- case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
- fixed_memory32 = &resource->data.fixed_memory32;
- addr->resource_type = ACPI_MEMORY_RANGE;
- addr->address.minimum = fixed_memory32->address;
- addr->address.address_length = fixed_memory32->address_length;
- addr->address.maximum = addr->address.minimum + addr->address.address_length - 1;
- return AE_OK;
- case ACPI_RESOURCE_TYPE_ADDRESS16:
- case ACPI_RESOURCE_TYPE_ADDRESS32:
- case ACPI_RESOURCE_TYPE_ADDRESS64:
- status = acpi_resource_to_address64(resource, addr);
- if (ACPI_SUCCESS(status) &&
- (addr->resource_type == ACPI_MEMORY_RANGE ||
- addr->resource_type == ACPI_IO_RANGE) &&
- addr->address.address_length > 0) {
- return AE_OK;
- }
- break;
- }
- return AE_ERROR;
-}
-
-static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
+static void validate_resources(struct device *dev, struct list_head *crs_res,
+ unsigned long type)
{
- struct pci_root_info *info = data;
- struct acpi_resource_address64 addr;
- acpi_status status;
-
- status = resource_to_addr(acpi_res, &addr);
- if (ACPI_SUCCESS(status))
- info->res_num++;
- return AE_OK;
-}
-
-static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
-{
- struct pci_root_info *info = data;
- struct resource *res;
- struct acpi_resource_address64 addr;
- acpi_status status;
- unsigned long flags;
- u64 start, orig_end, end, res_end;
-
- status = resource_to_addr(acpi_res, &addr);
- if (!ACPI_SUCCESS(status))
- return AE_OK;
-
- if (addr.resource_type == ACPI_MEMORY_RANGE) {
- flags = IORESOURCE_MEM;
- if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
- flags |= IORESOURCE_PREFETCH;
- res_end = (u64)iomem_resource.end;
- } else if (addr.resource_type == ACPI_IO_RANGE) {
- flags = IORESOURCE_IO;
- res_end = (u64)ioport_resource.end;
- } else
- return AE_OK;
-
- start = addr.address.minimum + addr.address.translation_offset;
- orig_end = end = addr.address.maximum + addr.address.translation_offset;
-
- /* Exclude non-addressable range or non-addressable portion of range */
- end = min(end, res_end);
- if (end <= start) {
- dev_info(&info->bridge->dev,
- "host bridge window [%#llx-%#llx] "
- "(ignored, not CPU addressable)\n", start, orig_end);
- return AE_OK;
- } else if (orig_end != end) {
- dev_info(&info->bridge->dev,
- "host bridge window [%#llx-%#llx] "
- "([%#llx-%#llx] ignored, not CPU addressable)\n",
- start, orig_end, end + 1, orig_end);
- }
+ LIST_HEAD(list);
+ struct resource *res1, *res2, *root = NULL;
+ struct resource_entry *tmp, *entry, *entry2;
- res = &info->res[info->res_num];
- res->name = info->name;
- res->flags = flags;
- res->start = start;
- res->end = end;
- info->res_offset[info->res_num] = addr.address.translation_offset;
- info->res_num++;
+ BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
+ root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
- if (!pci_use_crs)
- dev_printk(KERN_DEBUG, &info->bridge->dev,
- "host bridge window %pR (ignored)\n", res);
+ list_splice_init(crs_res, &list);
+ resource_list_for_each_entry_safe(entry, tmp, &list) {
+ bool free = false;
+ resource_size_t end;
- return AE_OK;
-}
-
-static void coalesce_windows(struct pci_root_info *info, unsigned long type)
-{
- int i, j;
- struct resource *res1, *res2;
-
- for (i = 0; i < info->res_num; i++) {
- res1 = &info->res[i];
+ res1 = entry->res;
if (!(res1->flags & type))
- continue;
+ goto next;
+
+ /* Exclude non-addressable range or non-addressable portion */
+ end = min(res1->end, root->end);
+ if (end <= res1->start) {
+ dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
+ res1);
+ free = true;
+ goto next;
+ } else if (res1->end != end) {
+ dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
+ res1, (unsigned long long)end + 1,
+ (unsigned long long)res1->end);
+ res1->end = end;
+ }
- for (j = i + 1; j < info->res_num; j++) {
- res2 = &info->res[j];
+ resource_list_for_each_entry(entry2, crs_res) {
+ res2 = entry2->res;
if (!(res2->flags & type))
continue;
@@ -355,118 +261,92 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
if (resource_overlaps(res1, res2)) {
res2->start = min(res1->start, res2->start);
res2->end = max(res1->end, res2->end);
- dev_info(&info->bridge->dev,
- "host bridge window expanded to %pR; %pR ignored\n",
+ dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
res2, res1);
- res1->flags = 0;
+ free = true;
+ goto next;
}
}
+
+next:
+ resource_list_del(entry);
+ if (free)
+ resource_list_free_entry(entry);
+ else
+ resource_list_add_tail(entry, crs_res);
}
}
static void add_resources(struct pci_root_info *info,
- struct list_head *resources)
+ struct list_head *resources,
+ struct list_head *crs_res)
{
- int i;
- struct resource *res, *root, *conflict;
-
- coalesce_windows(info, IORESOURCE_MEM);
- coalesce_windows(info, IORESOURCE_IO);
+ struct resource_entry *entry, *tmp;
+ struct resource *res, *conflict, *root = NULL;
- for (i = 0; i < info->res_num; i++) {
- res = &info->res[i];
+ validate_resources(&info->bridge->dev, crs_res, IORESOURCE_MEM);
+ validate_resources(&info->bridge->dev, crs_res, IORESOURCE_IO);
+ resource_list_for_each_entry_safe(entry, tmp, crs_res) {
+ res = entry->res;
if (res->flags & IORESOURCE_MEM)
root = &iomem_resource;
else if (res->flags & IORESOURCE_IO)
root = &ioport_resource;
else
- continue;
+ BUG_ON(res);
conflict = insert_resource_conflict(root, res);
- if (conflict)
+ if (conflict) {
dev_info(&info->bridge->dev,
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict);
- else
- pci_add_resource_offset(resources, res,
- info->res_offset[i]);
+ resource_list_destroy_entry(entry);
+ }
}
-}
-static void free_pci_root_info_res(struct pci_root_info *info)
-{
- kfree(info->res);
- info->res = NULL;
- kfree(info->res_offset);
- info->res_offset = NULL;
- info->res_num = 0;
+ list_splice_tail(crs_res, resources);
}
-static void __release_pci_root_info(struct pci_root_info *info)
+static void release_pci_root_info(struct pci_host_bridge *bridge)
{
- int i;
struct resource *res;
+ struct resource_entry *entry;
+ struct pci_root_info *info = bridge->release_data;
- for (i = 0; i < info->res_num; i++) {
- res = &info->res[i];
-
- if (!res->parent)
- continue;
-
- if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
- continue;
-
- release_resource(res);
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ res = entry->res;
+ if (res->parent &&
+ (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ release_resource(res);
}
- free_pci_root_info_res(info);
-
teardown_mcfg_map(info);
-
kfree(info);
}
-static void release_pci_root_info(struct pci_host_bridge *bridge)
-{
- struct pci_root_info *info = bridge->release_data;
-
- __release_pci_root_info(info);
-}
-
static void probe_pci_root_info(struct pci_root_info *info,
struct acpi_device *device,
- int busnum, int domain)
+ int busnum, int domain,
+ struct list_head *list)
{
- size_t size;
+ int ret;
+ struct resource_entry *entry;
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
info->bridge = device;
-
- info->res_num = 0;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
- info);
- if (!info->res_num)
- return;
-
- size = sizeof(*info->res) * info->res_num;
- info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
- if (!info->res) {
- info->res_num = 0;
- return;
- }
-
- size = sizeof(*info->res_offset) * info->res_num;
- info->res_num = 0;
- info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
- if (!info->res_offset) {
- kfree(info->res);
- info->res = NULL;
- return;
- }
-
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
- info);
+ ret = acpi_dev_get_resources(device, list,
+ acpi_dev_filter_resource_type_cb,
+ (void *)(IORESOURCE_IO | IORESOURCE_MEM));
+ if (ret < 0)
+ dev_warn(&device->dev,
+ "failed to parse _CRS method, error code %d\n", ret);
+ else if (ret == 0)
+ dev_dbg(&device->dev,
+ "no IO and memory resources present in _CRS\n");
+ else
+ resource_list_for_each_entry(entry, list)
+ entry->res->name = info->name;
}
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
@@ -475,6 +355,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
struct pci_root_info *info;
int domain = root->segment;
int busnum = root->secondary.start;
+ struct resource_entry *res_entry;
+ LIST_HEAD(crs_res);
LIST_HEAD(resources);
struct pci_bus *bus;
struct pci_sysdata *sd;
@@ -522,18 +404,22 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(info);
} else {
- probe_pci_root_info(info, device, busnum, domain);
-
/* insert busn res at first */
pci_add_resource(&resources, &root->secondary);
+
/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
- if (pci_use_crs)
- add_resources(info, &resources);
- else {
- free_pci_root_info_res(info);
+ probe_pci_root_info(info, device, busnum, domain, &crs_res);
+ if (pci_use_crs) {
+ add_resources(info, &resources, &crs_res);
+ } else {
+ resource_list_for_each_entry(res_entry, &crs_res)
+ dev_printk(KERN_DEBUG, &device->dev,
+ "host bridge window %pR (ignored)\n",
+ res_entry->res);
+ resource_list_free(&crs_res);
x86_pci_root_bus_resources(busnum, &resources);
}
@@ -548,8 +434,9 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
to_pci_host_bridge(bus->bridge),
release_pci_root_info, info);
} else {
- pci_free_resource_list(&resources);
- __release_pci_root_info(info);
+ resource_list_free(&resources);
+ teardown_mcfg_map(info);
+ kfree(info);
}
}
--
1.7.10.4
Some PCI device drivers assume that pci_dev->irq won't change after
calling pci_disable_device() and pci_enable_device() during suspend and
resume.
Commit c03b3b0738a5 ("x86, irq, mpparse: Release IOAPIC pin when
PCI device is disabled") frees PCI IRQ resources when pci_disable_device()
is called and reallocate IRQ resources when pci_enable_device() is
called again. This breaks above assumption. So commit 3eec595235c1
("x86, irq, PCI: Keep IRQ assignment for PCI devices during
suspend/hibernation") and 9eabc99a635a ("x86, irq, PCI: Keep IRQ
assignment for runtime power management") fix the issue by avoiding
freeing/reallocating IRQ resources during PCI device suspend/resume.
They achieve this by checking dev.power.is_prepared and
dev.power.runtime_status. PM maintainer, Rafael, then pointed out that
it's really an ugly fix which leaking PM internal state information to
IRQ subsystem.
Recently David Vrabel <[email protected]> also reports an
regression in pciback driver caused by commit cffe0a2b5a34 ("x86, irq:
Keep balance of IOAPIC pin reference count"). Please refer to:
http://lkml.org/lkml/2015/1/14/546
So this patch refine the way to release PCI IRQ resources. Instead of
releasing PCI IRQ resources in pci_disable_device()/
pcibios_disable_device(), we now release it at driver unbinding
notification BUS_NOTIFY_UNBOUND_DRIVER. In other word, we only release
PCI IRQ resources when there's no driver bound to the PCI device, and
it keeps the assumption that pci_dev->irq won't through multiple
invocation of pci_enable_device()/pci_disable_device().
Signed-off-by: Jiang Liu <[email protected]>
---
arch/x86/include/asm/pci_x86.h | 2 --
arch/x86/pci/common.c | 34 ++++++++++++++++++++++++++++------
arch/x86/pci/intel_mid_pci.c | 4 ++--
arch/x86/pci/irq.c | 15 +--------------
drivers/acpi/pci_irq.c | 9 +--------
5 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 164e3f8d3c3d..fa1195dae425 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -93,8 +93,6 @@ extern raw_spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
-extern bool mp_should_keep_irq(struct device *dev);
-
struct pci_raw_ops {
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val);
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7b20bccf3648..ff1f0afa5ed1 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -497,6 +497,31 @@ void __init pcibios_set_cache_line_size(void)
}
}
+/*
+ * Some device drivers assume dev->irq won't change after calling
+ * pci_disable_device(). So delay releasing of IRQ resource to driver
+ * unbinding time. Otherwise it will break PM subsystem and drivers
+ * like xen-pciback etc.
+ */
+static int pci_irq_notifier(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct pci_dev *dev = to_pci_dev(data);
+
+ if (action != BUS_NOTIFY_UNBOUND_DRIVER)
+ return NOTIFY_DONE;
+
+ if (pcibios_disable_irq)
+ pcibios_disable_irq(dev);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block pci_irq_nb = {
+ .notifier_call = pci_irq_notifier,
+ .priority = INT_MIN,
+};
+
int __init pcibios_init(void)
{
if (!raw_pci_ops) {
@@ -509,6 +534,9 @@ int __init pcibios_init(void)
if (pci_bf_sort >= pci_force_bf)
pci_sort_breadthfirst();
+
+ bus_register_notifier(&pci_bus_type, &pci_irq_nb);
+
return 0;
}
@@ -667,12 +695,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0;
}
-void pcibios_disable_device (struct pci_dev *dev)
-{
- if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
- pcibios_disable_irq(dev);
-}
-
int pci_ext_cfg_avail(void)
{
if (raw_pci_ext_ops)
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 44b9271580b5..95c2471f6819 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -234,10 +234,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
{
- if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
- dev->irq > 0) {
+ if (dev->irq_managed && dev->irq > 0) {
mp_unmap_irq(dev->irq);
dev->irq_managed = 0;
+ dev->irq = 0;
}
}
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 5dc6ca5e1741..e71b3dbd87b8 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1256,22 +1256,9 @@ static int pirq_enable_irq(struct pci_dev *dev)
return 0;
}
-bool mp_should_keep_irq(struct device *dev)
-{
- if (dev->power.is_prepared)
- return true;
-#ifdef CONFIG_PM
- if (dev->power.runtime_status == RPM_SUSPENDING)
- return true;
-#endif
-
- return false;
-}
-
static void pirq_disable_irq(struct pci_dev *dev)
{
- if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
- dev->irq_managed && dev->irq) {
+ if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
mp_unmap_irq(dev->irq);
dev->irq = 0;
dev->irq_managed = 0;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index b1def411c0b8..e7f718d6918a 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -485,14 +485,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (!pin || !dev->irq_managed || dev->irq <= 0)
return;
- /* Keep IOAPIC pin configuration when suspending */
- if (dev->dev.power.is_prepared)
- return;
-#ifdef CONFIG_PM
- if (dev->dev.power.runtime_status == RPM_SUSPENDING)
- return;
-#endif
-
entry = acpi_pci_irq_lookup(dev, pin);
if (!entry)
return;
@@ -513,5 +505,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (gsi >= 0) {
acpi_unregister_gsi(gsi);
dev->irq_managed = 0;
+ dev->irq = 0;
}
}
--
1.7.10.4
From: Yinghai Lu <[email protected]>
We need to parse APIC ID for IOAPIC registration for IOAPIC hotplug.
ACPI _MAT method and MADT table are used to figure out IOAPIC ID, just
like parsing CPU APIC ID for CPU hotplug.
[ tglx: Fixed docbook comment ]
Signed-off-by: Yinghai Lu <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Len Brown <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
drivers/acpi/processor_core.c | 123 ++++++++++++++++++++++++++++++++++++++---
include/linux/acpi.h | 4 ++
2 files changed, 118 insertions(+), 9 deletions(-)
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 02e48394276c..7962651cdbd4 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -4,6 +4,10 @@
*
* Alex Chiang <[email protected]>
* - Unified x86/ia64 implementations
+ *
+ * I/O APIC hotplug support
+ * Yinghai Lu <[email protected]>
+ * Jiang Liu <[email protected]>
*/
#include <linux/export.h>
#include <linux/acpi.h>
@@ -12,6 +16,21 @@
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_core");
+static struct acpi_table_madt *get_madt_table(void)
+{
+ static struct acpi_table_madt *madt;
+ static int read_madt;
+
+ if (!read_madt) {
+ if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
+ (struct acpi_table_header **)&madt)))
+ madt = NULL;
+ read_madt++;
+ }
+
+ return madt;
+}
+
static int map_lapic_id(struct acpi_subtable_header *entry,
u32 acpi_id, int *apic_id)
{
@@ -67,17 +86,10 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
static int map_madt_entry(int type, u32 acpi_id)
{
unsigned long madt_end, entry;
- static struct acpi_table_madt *madt;
- static int read_madt;
int phys_id = -1; /* CPU hardware ID */
+ struct acpi_table_madt *madt;
- if (!read_madt) {
- if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
- (struct acpi_table_header **)&madt)))
- madt = NULL;
- read_madt++;
- }
-
+ madt = get_madt_table();
if (!madt)
return phys_id;
@@ -203,3 +215,96 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
return acpi_map_cpuid(phys_id, acpi_id);
}
EXPORT_SYMBOL_GPL(acpi_get_cpuid);
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base,
+ u64 *phys_addr, int *ioapic_id)
+{
+ struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry;
+
+ if (ioapic->global_irq_base != gsi_base)
+ return 0;
+
+ *phys_addr = ioapic->address;
+ *ioapic_id = ioapic->id;
+ return 1;
+}
+
+static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr)
+{
+ struct acpi_subtable_header *hdr;
+ unsigned long madt_end, entry;
+ struct acpi_table_madt *madt;
+ int apic_id = -1;
+
+ madt = get_madt_table();
+ if (!madt)
+ return apic_id;
+
+ entry = (unsigned long)madt;
+ madt_end = entry + madt->header.length;
+
+ /* Parse all entries looking for a match. */
+ entry += sizeof(struct acpi_table_madt);
+ while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
+ hdr = (struct acpi_subtable_header *)entry;
+ if (hdr->type == ACPI_MADT_TYPE_IO_APIC &&
+ get_ioapic_id(hdr, gsi_base, phys_addr, &apic_id))
+ break;
+ else
+ entry += hdr->length;
+ }
+
+ return apic_id;
+}
+
+static int parse_mat_ioapic_entry(acpi_handle handle, u32 gsi_base,
+ u64 *phys_addr)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_subtable_header *header;
+ union acpi_object *obj;
+ int apic_id = -1;
+
+ if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+ goto exit;
+
+ if (!buffer.length || !buffer.pointer)
+ goto exit;
+
+ obj = buffer.pointer;
+ if (obj->type != ACPI_TYPE_BUFFER ||
+ obj->buffer.length < sizeof(struct acpi_subtable_header))
+ goto exit;
+
+ header = (struct acpi_subtable_header *)obj->buffer.pointer;
+ if (header->type == ACPI_MADT_TYPE_IO_APIC)
+ get_ioapic_id(header, gsi_base, phys_addr, &apic_id);
+
+exit:
+ kfree(buffer.pointer);
+ return apic_id;
+}
+
+/**
+ * acpi_get_ioapic_id - Get IOAPIC ID and physical address matching @gsi_base
+ * @handle: ACPI object for IOAPIC device
+ * @gsi_base: GSI base to match with
+ * @phys_addr: Pointer to store physical address of matching IOAPIC record
+ *
+ * Walk resources returned by ACPI_MAT method, then ACPI MADT table, to search
+ * for an ACPI IOAPIC record matching @gsi_base.
+ * Return IOAPIC id and store physical address in @phys_addr if found a match,
+ * otherwise return <0.
+ */
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr)
+{
+ int apic_id;
+
+ apic_id = parse_mat_ioapic_entry(handle, gsi_base, phys_addr);
+ if (apic_id == -1)
+ apic_id = parse_madt_ioapic_entry(gsi_base, phys_addr);
+
+ return apic_id;
+}
+#endif /* CONFIG_ACPI_HOTPLUG_IOAPIC */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index e53822148b6a..24c7aa8b1d20 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -152,6 +152,10 @@ int acpi_map_cpu(acpi_handle handle, int physid, int *pcpu);
int acpi_unmap_cpu(int cpu);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
+#endif
+
int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base);
--
1.7.10.4
Enable support of IOAPIC hotplug by:
1) reintroducing ACPI based IOAPIC driver
2) enhance pci_root driver to hook hotplug events
The ACPI IOAPIC driver is always enabled if all of ACPI, PCI and IOAPIC
are enabled.
Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Len Brown <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
---
drivers/acpi/Kconfig | 6 ++
drivers/acpi/Makefile | 1 +
drivers/acpi/internal.h | 7 ++
drivers/acpi/ioapic.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/acpi/pci_root.c | 3 +
5 files changed, 246 insertions(+)
create mode 100644 drivers/acpi/ioapic.c
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 8951cefb0a96..e6c3ddd92665 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -315,6 +315,12 @@ config ACPI_HOTPLUG_MEMORY
To compile this driver as a module, choose M here:
the module will be called acpi_memhotplug.
+config ACPI_HOTPLUG_IOAPIC
+ bool
+ depends on PCI
+ depends on X86_IO_APIC
+ default y
+
config ACPI_SBS
tristate "Smart Battery System"
depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index f74317cc1ca9..e59494c90402 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-y += container.o
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
obj-y += acpi_memhotplug.o
+obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_SBS) += sbshc.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 163e82f536fa..caca2805536d 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -35,6 +35,13 @@ void acpi_int340x_thermal_init(void);
int acpi_sysfs_init(void);
void acpi_container_init(void);
void acpi_memory_hotplug_init(void);
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_ioapic_add(struct acpi_pci_root *root);
+int acpi_ioapic_remove(struct acpi_pci_root *root);
+#else
+static inline int acpi_ioapic_add(struct acpi_pci_root *root) { return 0; }
+static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; }
+#endif
#ifdef CONFIG_ACPI_DOCK
void register_dock_dependent_device(struct acpi_device *adev,
acpi_handle dshandle);
diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c
new file mode 100644
index 000000000000..ccdc8db16bb8
--- /dev/null
+++ b/drivers/acpi/ioapic.c
@@ -0,0 +1,229 @@
+/*
+ * IOAPIC/IOxAPIC/IOSAPIC driver
+ *
+ * Copyright (C) 2009 Fujitsu Limited.
+ * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on original drivers/pci/ioapic.c
+ * Yinghai Lu <[email protected]>
+ * Jiang Liu <[email protected]>
+ */
+
+/*
+ * This driver manages I/O APICs added by hotplug after boot.
+ * We try to claim all I/O APIC devices, but those present at boot were
+ * registered when we parsed the ACPI MADT.
+ */
+
+#define pr_fmt(fmt) "ACPI : IOAPIC: " fmt
+
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <acpi/acpi.h>
+
+struct acpi_pci_ioapic {
+ acpi_handle root_handle;
+ acpi_handle handle;
+ u32 gsi_base;
+ struct resource res;
+ struct pci_dev *pdev;
+ struct list_head list;
+};
+
+static LIST_HEAD(ioapic_list);
+static DEFINE_MUTEX(ioapic_list_lock);
+
+static acpi_status setup_res(struct acpi_resource *acpi_res, void *data)
+{
+ struct resource *res = data;
+ struct resource_win win;
+
+ res->flags = 0;
+ if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0)
+ return AE_OK;
+
+ if (!acpi_dev_resource_memory(acpi_res, res)) {
+ if (acpi_dev_resource_address_space(acpi_res, &win) ||
+ acpi_dev_resource_ext_address_space(acpi_res, &win))
+ *res = win.res;
+ }
+ if ((res->flags & IORESOURCE_PREFETCH) ||
+ (res->flags & IORESOURCE_DISABLED))
+ res->flags = 0;
+
+ return AE_CTRL_TERMINATE;
+}
+
+static bool acpi_is_ioapic(acpi_handle handle, char **type)
+{
+ acpi_status status;
+ struct acpi_device_info *info;
+ char *hid = NULL;
+ bool match = false;
+
+ if (!acpi_has_method(handle, "_GSB"))
+ return false;
+
+ status = acpi_get_object_info(handle, &info);
+ if (ACPI_SUCCESS(status)) {
+ if (info->valid & ACPI_VALID_HID)
+ hid = info->hardware_id.string;
+ if (hid) {
+ if (strcmp(hid, "ACPI0009") == 0) {
+ *type = "IOxAPIC";
+ match = true;
+ } else if (strcmp(hid, "ACPI000A") == 0) {
+ *type = "IOAPIC";
+ match = true;
+ }
+ }
+ kfree(info);
+ }
+
+ return match;
+}
+
+static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl,
+ void *context, void **rv)
+{
+ acpi_status status;
+ unsigned long long gsi_base;
+ struct acpi_pci_ioapic *ioapic;
+ struct pci_dev *dev = NULL;
+ struct resource *res = NULL;
+ char *type = NULL;
+
+ if (!acpi_is_ioapic(handle, &type))
+ return AE_OK;
+
+ mutex_lock(&ioapic_list_lock);
+ list_for_each_entry(ioapic, &ioapic_list, list)
+ if (ioapic->handle == handle) {
+ mutex_unlock(&ioapic_list_lock);
+ return AE_OK;
+ }
+
+ status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsi_base);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_warn(handle, "failed to evaluate _GSB method\n");
+ goto exit;
+ }
+
+ ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
+ if (!ioapic) {
+ pr_err("cannot allocate memory for new IOAPIC\n");
+ goto exit;
+ } else {
+ ioapic->root_handle = (acpi_handle)context;
+ ioapic->handle = handle;
+ ioapic->gsi_base = (u32)gsi_base;
+ INIT_LIST_HEAD(&ioapic->list);
+ }
+
+ if (acpi_ioapic_registered(handle, (u32)gsi_base))
+ goto done;
+
+ dev = acpi_get_pci_dev(handle);
+ if (dev && pci_resource_len(dev, 0)) {
+ if (pci_enable_device(dev) < 0)
+ goto exit_put;
+ pci_set_master(dev);
+ if (pci_request_region(dev, 0, type))
+ goto exit_disable;
+ res = &dev->resource[0];
+ ioapic->pdev = dev;
+ } else {
+ pci_dev_put(dev);
+ dev = NULL;
+
+ res = &ioapic->res;
+ acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res);
+ if (res->flags == 0) {
+ acpi_handle_warn(handle, "failed to get resource\n");
+ goto exit_free;
+ } else if (request_resource(&iomem_resource, res)) {
+ acpi_handle_warn(handle, "failed to insert resource\n");
+ goto exit_free;
+ }
+ }
+
+ if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) {
+ acpi_handle_warn(handle, "failed to register IOAPIC\n");
+ goto exit_release;
+ }
+done:
+ list_add(&ioapic->list, &ioapic_list);
+ mutex_unlock(&ioapic_list_lock);
+
+ if (dev)
+ dev_info(&dev->dev, "%s at %pR, GSI %u\n",
+ type, res, (u32)gsi_base);
+ else
+ acpi_handle_info(handle, "%s at %pR, GSI %u\n",
+ type, res, (u32)gsi_base);
+
+ return AE_OK;
+
+exit_release:
+ if (dev)
+ pci_release_region(dev, 0);
+ else
+ release_resource(res);
+exit_disable:
+ if (dev)
+ pci_disable_device(dev);
+exit_put:
+ pci_dev_put(dev);
+exit_free:
+ kfree(ioapic);
+exit:
+ mutex_unlock(&ioapic_list_lock);
+ *(acpi_status *)rv = AE_ERROR;
+ return AE_OK;
+}
+
+int acpi_ioapic_add(struct acpi_pci_root *root)
+{
+ acpi_status status, retval = AE_OK;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle,
+ UINT_MAX, handle_ioapic_add, NULL,
+ root->device->handle, (void **)&retval);
+
+ return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV;
+}
+
+int acpi_ioapic_remove(struct acpi_pci_root *root)
+{
+ int retval = 0;
+ struct acpi_pci_ioapic *ioapic, *tmp;
+
+ mutex_lock(&ioapic_list_lock);
+ list_for_each_entry_safe(ioapic, tmp, &ioapic_list, list) {
+ if (root->device->handle != ioapic->root_handle)
+ continue;
+
+ if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base))
+ retval = -EBUSY;
+
+ if (ioapic->pdev) {
+ pci_release_region(ioapic->pdev, 0);
+ pci_disable_device(ioapic->pdev);
+ pci_dev_put(ioapic->pdev);
+ } else if (ioapic->res.flags && ioapic->res.parent) {
+ release_resource(&ioapic->res);
+ }
+ list_del(&ioapic->list);
+ kfree(ioapic);
+ }
+ mutex_unlock(&ioapic_list_lock);
+
+ return retval;
+}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index e53e0f659204..68a5f712cd19 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -621,6 +621,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (hotadd) {
pcibios_resource_survey_bus(root->bus);
pci_assign_unassigned_root_bus_resources(root->bus);
+ acpi_ioapic_add(root);
}
pci_lock_rescan_remove();
@@ -644,6 +645,8 @@ static void acpi_pci_root_remove(struct acpi_device *device)
pci_stop_root_bus(root->bus);
+ WARN_ON(acpi_ioapic_remove(root));
+
device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device);
--
1.7.10.4
On 05/02/15 05:44, Jiang Liu wrote:
>
> --- a/drivers/xen/xen-acpi-memhotplug.c
> +++ b/drivers/xen/xen-acpi-memhotplug.c
> @@ -117,8 +117,8 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
> list_for_each_entry(info, &mem_device->res_list, list) {
> if ((info->caching == address64.info.mem.caching) &&
> (info->write_protect == address64.info.mem.write_protect) &&
> - (info->start_addr + info->length == address64.minimum)) {
> - info->length += address64.address_length;
> + (info->start_addr + info->length == address64.address.minimum)) {
> + info->length += address64.address.address_length;
> return AE_OK;
> }
> }
> @@ -130,8 +130,8 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
> INIT_LIST_HEAD(&new->list);
> new->caching = address64.info.mem.caching;
> new->write_protect = address64.info.mem.write_protect;
> - new->start_addr = address64.minimum;
> - new->length = address64.address_length;
> + new->start_addr = address64.address.minimum;
> + new->length = address64.address.address_length;
> list_add_tail(&new->list, &mem_device->res_list);
>
> return AE_OK;
Xen parts:
Acked-by: David Vrabel <[email protected]>
David
On Thursday, February 05, 2015 01:44:26 PM Jiang Liu wrote:
> During enabling ACPI based IOAPIC hotplug, Thomas noticed some issues
> in ACPI resource parsing interfaces. So this is an effort to improve them.
>
> Patch 1 refines ACPICA resource descriptors, which has already been
> merged into "git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git bleeding-edge"
>
> Patch 2-12 improve ACPI resource parsing interfaces and also fixes some
> bugs.
>
> Patch 13-20 try to share the common data structure resource_list_entry
> between PCI and ACPI. It may also be shared with PNP too.
>
> Patch 21-23 enable ACPI based IOAPIC hotplug.
>
> The patchset is based on v3.19-rc6+ and passed Fengguang's 0day test
> suite. You may get it from:
> https://github.com/jiangliu/linux.git acpires_v2
>
> V3->V4:
> 1) rename resource_list_entry as resource_entry to avoid conflicts
> 2) kill pcibios_disable_device()
> 3) Patch 1-16 are the same with v3
OK, I've applied patches [17-23/23] on top of the previous [1-16/23], thanks!
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
> -----Original Message-----
> From: Jiang Liu [mailto:[email protected]]
> Sent: Wednesday, February 4, 2015 9:44 PM
> To: Rafael J. Wysocki; Thomas Gleixner; Bjorn Helgaas; Yinghai Lu; Borislav
> Petkov; Lv Zheng; Tony Luck; Fenghua Yu; Ingo Molnar; H. Peter Anvin;
> [email protected]; Len Brown; Robert Moore; Clemens Ladisch; Arnd
> Bergmann; Greg Kroah-Hartman; KY Srinivasan; Haiyang Zhang; Konrad
> Rzeszutek Wilk; Boris Ostrovsky; David Vrabel
> Cc: [email protected]; [email protected]; linux-
> [email protected]; Jiang Liu; [email protected];
> [email protected]; [email protected]; xen-
> [email protected]
> Subject: [Patch v4 01/23] ACPICA: Resources: Provide common part for struct
> acpi_resource_address structures.
>
> From: Lv Zheng <[email protected]>
>
> struct acpi_resource_address and struct
> acpi_resource_extended_address64 share substracts just at different
> offsets. To unify the parsing functions, OSPMs like Linux need a new
> ACPI_ADDRESS64_ATTRIBUTE as their substructs, so they can extract the
> shared data.
>
> This patch also synchronizes the structure changes to the Linux kernel.
> The usages are searched by matching the following keywords:
> 1. acpi_resource_address
> 2. acpi_resource_extended_address
> 3. ACPI_RESOURCE_TYPE_ADDRESS
> 4. ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS
> And we found and fixed the usages in the following files:
> arch/ia64/kernel/acpi-ext.c
> arch/ia64/pci/pci.c
> arch/x86/pci/acpi.c
> arch/x86/pci/mmconfig-shared.c
> drivers/xen/xen-acpi-memhotplug.c
> drivers/acpi/acpi_memhotplug.c
> drivers/acpi/pci_root.c
> drivers/acpi/resource.c
> drivers/char/hpet.c
> drivers/pnp/pnpacpi/rsparser.c
> drivers/hv/vmbus_drv.c
>
> Build tests are passed with defconfig/allnoconfig/allyesconfig and
> defconfig+CONFIG_ACPI=n.
>
> Original-by: Thomas Gleixner <[email protected]>
> Original-by: Jiang Liu <[email protected]>
> Signed-off-by: Lv Zheng <[email protected]>
> Signed-off-by: Jiang Liu <[email protected]>
Hyper-V parts:
Acked-by: K. Y. Srinivasan <[email protected]>
> ---
> arch/ia64/kernel/acpi-ext.c | 6 ++--
> arch/ia64/pci/pci.c | 14 ++++-----
> arch/x86/pci/acpi.c | 26 ++++++++--------
> arch/x86/pci/mmconfig-shared.c | 6 ++--
> drivers/acpi/acpi_memhotplug.c | 8 ++---
> drivers/acpi/acpica/rsaddr.c | 9 +++---
> drivers/acpi/acpica/rsdumpinfo.c | 59 +++++++++++++++++++--------------
> ----
> drivers/acpi/acpica/rsxface.c | 10 +++----
> drivers/acpi/pci_root.c | 6 ++--
> drivers/acpi/resource.c | 24 +++++++--------
> drivers/char/hpet.c | 4 +--
> drivers/hv/vmbus_drv.c | 4 +--
> drivers/pnp/pnpacpi/rsparser.c | 16 +++++-----
> drivers/xen/xen-acpi-memhotplug.c | 8 ++---
> include/acpi/acrestyp.h | 40 +++++++++++++++----------
> 15 files changed, 125 insertions(+), 115 deletions(-)
>
> diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c index
> 8b9318d311a0..bd09bf74f187 100644
> --- a/arch/ia64/kernel/acpi-ext.c
> +++ b/arch/ia64/kernel/acpi-ext.c
> @@ -69,10 +69,10 @@ static acpi_status find_csr_space(struct acpi_resource
> *resource, void *data)
> status = acpi_resource_to_address64(resource, &addr);
> if (ACPI_SUCCESS(status) &&
> addr.resource_type == ACPI_MEMORY_RANGE &&
> - addr.address_length &&
> + addr.address.address_length &&
> addr.producer_consumer == ACPI_CONSUMER) {
> - space->base = addr.minimum;
> - space->length = addr.address_length;
> + space->base = addr.address.minimum;
> + space->length = addr.address.address_length;
> return AE_CTRL_TERMINATE;
> }
> return AE_OK; /* keep looking */
> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index
> 900cc93e5409..48cc65705db4 100644
> --- a/arch/ia64/pci/pci.c
> +++ b/arch/ia64/pci/pci.c
> @@ -188,12 +188,12 @@ static u64 add_io_space(struct pci_root_info *info,
>
> name = (char *)(iospace + 1);
>
> - min = addr->minimum;
> - max = min + addr->address_length - 1;
> + min = addr->address.minimum;
> + max = min + addr->address.address_length - 1;
> if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION)
> sparse = 1;
>
> - space_nr = new_space(addr->translation_offset, sparse);
> + space_nr = new_space(addr->address.translation_offset, sparse);
> if (space_nr == ~0)
> goto free_resource;
>
> @@ -247,7 +247,7 @@ static acpi_status resource_to_window(struct
> acpi_resource *resource,
> if (ACPI_SUCCESS(status) &&
> (addr->resource_type == ACPI_MEMORY_RANGE ||
> addr->resource_type == ACPI_IO_RANGE) &&
> - addr->address_length &&
> + addr->address.address_length &&
> addr->producer_consumer == ACPI_PRODUCER)
> return AE_OK;
>
> @@ -284,7 +284,7 @@ static acpi_status add_window(struct acpi_resource
> *res, void *data)
> if (addr.resource_type == ACPI_MEMORY_RANGE) {
> flags = IORESOURCE_MEM;
> root = &iomem_resource;
> - offset = addr.translation_offset;
> + offset = addr.address.translation_offset;
> } else if (addr.resource_type == ACPI_IO_RANGE) {
> flags = IORESOURCE_IO;
> root = &ioport_resource;
> @@ -297,8 +297,8 @@ static acpi_status add_window(struct acpi_resource
> *res, void *data)
> resource = &info->res[info->res_num];
> resource->name = info->name;
> resource->flags = flags;
> - resource->start = addr.minimum + offset;
> - resource->end = resource->start + addr.address_length - 1;
> + resource->start = addr.address.minimum + offset;
> + resource->end = resource->start + addr.address.address_length - 1;
> info->res_offset[info->res_num] = offset;
>
> if (insert_resource(root, resource)) { diff --git a/arch/x86/pci/acpi.c
> b/arch/x86/pci/acpi.c index cfd1b132b8e3..bb98afd0591e 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -231,23 +231,23 @@ static acpi_status resource_to_addr(struct
> acpi_resource *resource,
> case ACPI_RESOURCE_TYPE_MEMORY24:
> memory24 = &resource->data.memory24;
> addr->resource_type = ACPI_MEMORY_RANGE;
> - addr->minimum = memory24->minimum;
> - addr->address_length = memory24->address_length;
> - addr->maximum = addr->minimum + addr->address_length -
> 1;
> + addr->address.minimum = memory24->minimum;
> + addr->address.address_length = memory24-
> >address_length;
> + addr->address.maximum = addr->address.minimum +
> +addr->address.address_length - 1;
> return AE_OK;
> case ACPI_RESOURCE_TYPE_MEMORY32:
> memory32 = &resource->data.memory32;
> addr->resource_type = ACPI_MEMORY_RANGE;
> - addr->minimum = memory32->minimum;
> - addr->address_length = memory32->address_length;
> - addr->maximum = addr->minimum + addr->address_length -
> 1;
> + addr->address.minimum = memory32->minimum;
> + addr->address.address_length = memory32-
> >address_length;
> + addr->address.maximum = addr->address.minimum +
> +addr->address.address_length - 1;
> return AE_OK;
> case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> fixed_memory32 = &resource->data.fixed_memory32;
> addr->resource_type = ACPI_MEMORY_RANGE;
> - addr->minimum = fixed_memory32->address;
> - addr->address_length = fixed_memory32->address_length;
> - addr->maximum = addr->minimum + addr->address_length -
> 1;
> + addr->address.minimum = fixed_memory32->address;
> + addr->address.address_length = fixed_memory32-
> >address_length;
> + addr->address.maximum = addr->address.minimum +
> +addr->address.address_length - 1;
> return AE_OK;
> case ACPI_RESOURCE_TYPE_ADDRESS16:
> case ACPI_RESOURCE_TYPE_ADDRESS32:
> @@ -256,7 +256,7 @@ static acpi_status resource_to_addr(struct
> acpi_resource *resource,
> if (ACPI_SUCCESS(status) &&
> (addr->resource_type == ACPI_MEMORY_RANGE ||
> addr->resource_type == ACPI_IO_RANGE) &&
> - addr->address_length > 0) {
> + addr->address.address_length > 0) {
> return AE_OK;
> }
> break;
> @@ -298,8 +298,8 @@ static acpi_status setup_resource(struct
> acpi_resource *acpi_res, void *data)
> } else
> return AE_OK;
>
> - start = addr.minimum + addr.translation_offset;
> - orig_end = end = addr.maximum + addr.translation_offset;
> + start = addr.address.minimum + addr.address.translation_offset;
> + orig_end = end = addr.address.maximum +
> +addr.address.translation_offset;
>
> /* Exclude non-addressable range or non-addressable portion of
> range */
> end = min(end, (u64)iomem_resource.end); @@ -320,7 +320,7 @@
> static acpi_status setup_resource(struct acpi_resource *acpi_res, void
> *data)
> res->flags = flags;
> res->start = start;
> res->end = end;
> - info->res_offset[info->res_num] = addr.translation_offset;
> + info->res_offset[info->res_num] = addr.address.translation_offset;
> info->res_num++;
>
> if (!pci_use_crs)
> diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-
> shared.c index 326198a4434e..5a8dceac3094 100644
> --- a/arch/x86/pci/mmconfig-shared.c
> +++ b/arch/x86/pci/mmconfig-shared.c
> @@ -397,12 +397,12 @@ static acpi_status check_mcfg_resource(struct
> acpi_resource *res, void *data)
>
> status = acpi_resource_to_address64(res, &address);
> if (ACPI_FAILURE(status) ||
> - (address.address_length <= 0) ||
> + (address.address.address_length <= 0) ||
> (address.resource_type != ACPI_MEMORY_RANGE))
> return AE_OK;
>
> - if ((mcfg_res->start >= address.minimum) &&
> - (mcfg_res->end < (address.minimum + address.address_length)))
> {
> + if ((mcfg_res->start >= address.address.minimum) &&
> + (mcfg_res->end < (address.address.minimum +
> +address.address.address_length))) {
> mcfg_res->flags = 1;
> return AE_CTRL_TERMINATE;
> }
> diff --git a/drivers/acpi/acpi_memhotplug.c
> b/drivers/acpi/acpi_memhotplug.c index 23e2319ead41..ee28f4d15625
> 100644
> --- a/drivers/acpi/acpi_memhotplug.c
> +++ b/drivers/acpi/acpi_memhotplug.c
> @@ -101,8 +101,8 @@ acpi_memory_get_resource(struct acpi_resource
> *resource, void *context)
> /* Can we combine the resource range information? */
> if ((info->caching == address64.info.mem.caching) &&
> (info->write_protect ==
> address64.info.mem.write_protect) &&
> - (info->start_addr + info->length == address64.minimum)) {
> - info->length += address64.address_length;
> + (info->start_addr + info->length ==
> address64.address.minimum)) {
> + info->length += address64.address.address_length;
> return AE_OK;
> }
> }
> @@ -114,8 +114,8 @@ acpi_memory_get_resource(struct acpi_resource
> *resource, void *context)
> INIT_LIST_HEAD(&new->list);
> new->caching = address64.info.mem.caching;
> new->write_protect = address64.info.mem.write_protect;
> - new->start_addr = address64.minimum;
> - new->length = address64.address_length;
> + new->start_addr = address64.address.minimum;
> + new->length = address64.address.address_length;
> list_add_tail(&new->list, &mem_device->res_list);
>
> return AE_OK;
> diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index
> 916fd095ff34..94a3a057042c 100644
> --- a/drivers/acpi/acpica/rsaddr.c
> +++ b/drivers/acpi/acpica/rsaddr.c
> @@ -74,7 +74,7 @@ struct acpi_rsconvert_info
> acpi_rs_convert_address16[5] = {
> * Address Translation Offset
> * Address Length
> */
> - {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.granularity),
> + {ACPI_RSC_MOVE16,
> ACPI_RS_OFFSET(data.address16.address.granularity),
> AML_OFFSET(address16.granularity),
> 5},
>
> @@ -112,7 +112,7 @@ struct acpi_rsconvert_info
> acpi_rs_convert_address32[5] = {
> * Address Translation Offset
> * Address Length
> */
> - {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.granularity),
> + {ACPI_RSC_MOVE32,
> ACPI_RS_OFFSET(data.address32.address.granularity),
> AML_OFFSET(address32.granularity),
> 5},
>
> @@ -150,7 +150,7 @@ struct acpi_rsconvert_info
> acpi_rs_convert_address64[5] = {
> * Address Translation Offset
> * Address Length
> */
> - {ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.granularity),
> + {ACPI_RSC_MOVE64,
> ACPI_RS_OFFSET(data.address64.address.granularity),
> AML_OFFSET(address64.granularity),
> 5},
>
> @@ -194,7 +194,8 @@ struct acpi_rsconvert_info
> acpi_rs_convert_ext_address64[5] = {
> * Address Length
> * Type-Specific Attribute
> */
> - {ACPI_RSC_MOVE64,
> ACPI_RS_OFFSET(data.ext_address64.granularity),
> + {ACPI_RSC_MOVE64,
> + ACPI_RS_OFFSET(data.ext_address64.address.granularity),
> AML_OFFSET(ext_address64.granularity),
> 6}
> };
> diff --git a/drivers/acpi/acpica/rsdumpinfo.c
> b/drivers/acpi/acpica/rsdumpinfo.c
> index 2f9332d5c973..6ba7ad5faa9c 100644
> --- a/drivers/acpi/acpica/rsdumpinfo.c
> +++ b/drivers/acpi/acpica/rsdumpinfo.c
> @@ -183,15 +183,15 @@ struct acpi_rsdump_info
> acpi_rs_dump_address16[8] = {
> {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address16),
> "16-Bit WORD Address Space", NULL},
> {ACPI_RSD_ADDRESS, 0, NULL, NULL},
> - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.granularity),
> "Granularity",
> - NULL},
> - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.minimum),
> "Address Minimum",
> - NULL},
> - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.maximum),
> "Address Maximum",
> - NULL},
> - {ACPI_RSD_UINT16,
> ACPI_RSD_OFFSET(address16.translation_offset),
> + {ACPI_RSD_UINT16,
> ACPI_RSD_OFFSET(address16.address.granularity),
> + "Granularity", NULL},
> + {ACPI_RSD_UINT16,
> ACPI_RSD_OFFSET(address16.address.minimum),
> + "Address Minimum", NULL},
> + {ACPI_RSD_UINT16,
> ACPI_RSD_OFFSET(address16.address.maximum),
> + "Address Maximum", NULL},
> + {ACPI_RSD_UINT16,
> +ACPI_RSD_OFFSET(address16.address.translation_offset),
> "Translation Offset", NULL},
> - {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(address16.address_length),
> + {ACPI_RSD_UINT16,
> ACPI_RSD_OFFSET(address16.address.address_length),
> "Address Length", NULL},
> {ACPI_RSD_SOURCE,
> ACPI_RSD_OFFSET(address16.resource_source), NULL, NULL} }; @@ -200,15
> +200,15 @@ struct acpi_rsdump_info acpi_rs_dump_address32[8] = {
> {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address32),
> "32-Bit DWORD Address Space", NULL},
> {ACPI_RSD_ADDRESS, 0, NULL, NULL},
> - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.granularity),
> "Granularity",
> - NULL},
> - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.minimum),
> "Address Minimum",
> - NULL},
> - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.maximum),
> "Address Maximum",
> - NULL},
> - {ACPI_RSD_UINT32,
> ACPI_RSD_OFFSET(address32.translation_offset),
> + {ACPI_RSD_UINT32,
> ACPI_RSD_OFFSET(address32.address.granularity),
> + "Granularity", NULL},
> + {ACPI_RSD_UINT32,
> ACPI_RSD_OFFSET(address32.address.minimum),
> + "Address Minimum", NULL},
> + {ACPI_RSD_UINT32,
> ACPI_RSD_OFFSET(address32.address.maximum),
> + "Address Maximum", NULL},
> + {ACPI_RSD_UINT32,
> +ACPI_RSD_OFFSET(address32.address.translation_offset),
> "Translation Offset", NULL},
> - {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(address32.address_length),
> + {ACPI_RSD_UINT32,
> ACPI_RSD_OFFSET(address32.address.address_length),
> "Address Length", NULL},
> {ACPI_RSD_SOURCE,
> ACPI_RSD_OFFSET(address32.resource_source), NULL, NULL} }; @@ -217,15
> +217,15 @@ struct acpi_rsdump_info acpi_rs_dump_address64[8] = {
> {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_address64),
> "64-Bit QWORD Address Space", NULL},
> {ACPI_RSD_ADDRESS, 0, NULL, NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.granularity),
> "Granularity",
> - NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.minimum),
> "Address Minimum",
> - NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.maximum),
> "Address Maximum",
> - NULL},
> - {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(address64.translation_offset),
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(address64.address.granularity),
> + "Granularity", NULL},
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(address64.address.minimum),
> + "Address Minimum", NULL},
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(address64.address.maximum),
> + "Address Maximum", NULL},
> + {ACPI_RSD_UINT64,
> +ACPI_RSD_OFFSET(address64.address.translation_offset),
> "Translation Offset", NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(address64.address_length),
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(address64.address.address_length),
> "Address Length", NULL},
> {ACPI_RSD_SOURCE,
> ACPI_RSD_OFFSET(address64.resource_source), NULL, NULL} }; @@ -234,15
> +234,16 @@ struct acpi_rsdump_info acpi_rs_dump_ext_address64[8] = {
> {ACPI_RSD_TITLE,
> ACPI_RSD_TABLE_SIZE(acpi_rs_dump_ext_address64),
> "64-Bit Extended Address Space", NULL},
> {ACPI_RSD_ADDRESS, 0, NULL, NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.granularity),
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(ext_address64.address.granularity),
> "Granularity", NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.minimum),
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(ext_address64.address.minimum),
> "Address Minimum", NULL},
> - {ACPI_RSD_UINT64, ACPI_RSD_OFFSET(ext_address64.maximum),
> + {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(ext_address64.address.maximum),
> "Address Maximum", NULL},
> - {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(ext_address64.translation_offset),
> + {ACPI_RSD_UINT64,
> + ACPI_RSD_OFFSET(ext_address64.address.translation_offset),
> "Translation Offset", NULL},
> - {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(ext_address64.address_length),
> + {ACPI_RSD_UINT64,
> +ACPI_RSD_OFFSET(ext_address64.address.address_length),
> "Address Length", NULL},
> {ACPI_RSD_UINT64,
> ACPI_RSD_OFFSET(ext_address64.type_specific),
> "Type-Specific Attribute", NULL}
> diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index
> 877ab9202133..295287891174 100644
> --- a/drivers/acpi/acpica/rsxface.c
> +++ b/drivers/acpi/acpica/rsxface.c
> @@ -60,11 +60,11 @@ ACPI_MODULE_NAME("rsxface")
> ACPI_COPY_FIELD(out, in, min_address_fixed); \
> ACPI_COPY_FIELD(out, in, max_address_fixed); \
> ACPI_COPY_FIELD(out, in, info); \
> - ACPI_COPY_FIELD(out, in, granularity); \
> - ACPI_COPY_FIELD(out, in, minimum); \
> - ACPI_COPY_FIELD(out, in, maximum); \
> - ACPI_COPY_FIELD(out, in, translation_offset); \
> - ACPI_COPY_FIELD(out, in, address_length); \
> + ACPI_COPY_FIELD(out, in, address.granularity); \
> + ACPI_COPY_FIELD(out, in, address.minimum); \
> + ACPI_COPY_FIELD(out, in, address.maximum); \
> + ACPI_COPY_FIELD(out, in, address.translation_offset); \
> + ACPI_COPY_FIELD(out, in, address.address_length); \
> ACPI_COPY_FIELD(out, in, resource_source);
> /* Local prototypes */
> static acpi_status
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index
> c6bcb8c719d8..e53e0f659204 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -112,10 +112,10 @@ get_root_bridge_busnr_callback(struct
> acpi_resource *resource, void *data)
> if (ACPI_FAILURE(status))
> return AE_OK;
>
> - if ((address.address_length > 0) &&
> + if ((address.address.address_length > 0) &&
> (address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
> - res->start = address.minimum;
> - res->end = address.minimum + address.address_length - 1;
> + res->start = address.address.minimum;
> + res->end = address.address.minimum +
> address.address.address_length -
> +1;
> }
>
> return AE_OK;
> diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index
> 782a0d15c25f..d0a4d90c6bcc 100644
> --- a/drivers/acpi/resource.c
> +++ b/drivers/acpi/resource.c
> @@ -202,22 +202,22 @@ bool acpi_dev_resource_address_space(struct
> acpi_resource *ares,
> if (ACPI_FAILURE(status))
> return false;
>
> - res->start = addr.minimum;
> - res->end = addr.maximum;
> + res->start = addr.address.minimum;
> + res->end = addr.address.maximum;
> window = addr.producer_consumer == ACPI_PRODUCER;
>
> switch(addr.resource_type) {
> case ACPI_MEMORY_RANGE:
> - len = addr.maximum - addr.minimum + 1;
> + len = addr.address.maximum - addr.address.minimum + 1;
> res->flags = acpi_dev_memresource_flags(len,
>
> addr.info.mem.write_protect,
> window);
> break;
> case ACPI_IO_RANGE:
> - io_decode = addr.granularity == 0xfff ?
> + io_decode = addr.address.granularity == 0xfff ?
> ACPI_DECODE_10 : ACPI_DECODE_16;
> - res->flags = acpi_dev_ioresource_flags(addr.minimum,
> - addr.maximum,
> + res->flags =
> acpi_dev_ioresource_flags(addr.address.minimum,
> + addr.address.maximum,
> io_decode, window);
> break;
> case ACPI_BUS_NUMBER_RANGE:
> @@ -253,22 +253,22 @@ bool acpi_dev_resource_ext_address_space(struct
> acpi_resource *ares,
>
> ext_addr = &ares->data.ext_address64;
>
> - res->start = ext_addr->minimum;
> - res->end = ext_addr->maximum;
> + res->start = ext_addr->address.minimum;
> + res->end = ext_addr->address.maximum;
> window = ext_addr->producer_consumer == ACPI_PRODUCER;
>
> switch(ext_addr->resource_type) {
> case ACPI_MEMORY_RANGE:
> - len = ext_addr->maximum - ext_addr->minimum + 1;
> + len = ext_addr->address.maximum - ext_addr-
> >address.minimum + 1;
> res->flags = acpi_dev_memresource_flags(len,
> ext_addr->info.mem.write_protect,
> window);
> break;
> case ACPI_IO_RANGE:
> - io_decode = ext_addr->granularity == 0xfff ?
> + io_decode = ext_addr->address.granularity == 0xfff ?
> ACPI_DECODE_10 : ACPI_DECODE_16;
> - res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
> - ext_addr->maximum,
> + res->flags = acpi_dev_ioresource_flags(ext_addr-
> >address.minimum,
> + ext_addr-
> >address.maximum,
> io_decode, window);
> break;
> case ACPI_BUS_NUMBER_RANGE:
> diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index
> d5d4cd82b9f7..5c0baa9ffc64 100644
> --- a/drivers/char/hpet.c
> +++ b/drivers/char/hpet.c
> @@ -976,8 +976,8 @@ static acpi_status hpet_resources(struct
> acpi_resource *res, void *data)
> status = acpi_resource_to_address64(res, &addr);
>
> if (ACPI_SUCCESS(status)) {
> - hdp->hd_phys_address = addr.minimum;
> - hdp->hd_address = ioremap(addr.minimum,
> addr.address_length);
> + hdp->hd_phys_address = addr.address.minimum;
> + hdp->hd_address = ioremap(addr.address.minimum,
> +addr.address.address_length);
>
> if (hpet_is_known(hdp)) {
> iounmap(hdp->hd_address);
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index
> 4d6b26979fbd..bb3725b672cf 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -861,8 +861,8 @@ static acpi_status vmbus_walk_resources(struct
> acpi_resource *res, void *ctx)
> break;
>
> case ACPI_RESOURCE_TYPE_ADDRESS64:
> - hyperv_mmio.start = res->data.address64.minimum;
> - hyperv_mmio.end = res->data.address64.maximum;
> + hyperv_mmio.start = res-
> >data.address64.address.minimum;
> + hyperv_mmio.end = res->data.address64.address.maximum;
> break;
> }
>
> diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
> index 66977ebf13b3..2d9bc789af0f 100644
> --- a/drivers/pnp/pnpacpi/rsparser.c
> +++ b/drivers/pnp/pnpacpi/rsparser.c
> @@ -410,12 +410,12 @@ static __init void
> pnpacpi_parse_address_option(struct pnp_dev *dev,
> if (p->resource_type == ACPI_MEMORY_RANGE) {
> if (p->info.mem.write_protect ==
> ACPI_READ_WRITE_MEMORY)
> flags = IORESOURCE_MEM_WRITEABLE;
> - pnp_register_mem_resource(dev, option_flags, p-
> >minimum,
> - p->minimum, 0, p->address_length,
> + pnp_register_mem_resource(dev, option_flags, p-
> >address.minimum,
> + p->address.minimum, 0, p-
> >address.address_length,
> flags);
> } else if (p->resource_type == ACPI_IO_RANGE)
> - pnp_register_port_resource(dev, option_flags, p-
> >minimum,
> - p->minimum, 0, p->address_length,
> + pnp_register_port_resource(dev, option_flags, p-
> >address.minimum,
> + p->address.minimum, 0, p-
> >address.address_length,
> IORESOURCE_IO_FIXED);
> }
>
> @@ -429,12 +429,12 @@ static __init void
> pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
> if (p->resource_type == ACPI_MEMORY_RANGE) {
> if (p->info.mem.write_protect ==
> ACPI_READ_WRITE_MEMORY)
> flags = IORESOURCE_MEM_WRITEABLE;
> - pnp_register_mem_resource(dev, option_flags, p-
> >minimum,
> - p->minimum, 0, p->address_length,
> + pnp_register_mem_resource(dev, option_flags, p-
> >address.minimum,
> + p->address.minimum, 0, p-
> >address.address_length,
> flags);
> } else if (p->resource_type == ACPI_IO_RANGE)
> - pnp_register_port_resource(dev, option_flags, p-
> >minimum,
> - p->minimum, 0, p->address_length,
> + pnp_register_port_resource(dev, option_flags, p-
> >address.minimum,
> + p->address.minimum, 0, p-
> >address.address_length,
> IORESOURCE_IO_FIXED);
> }
>
> diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-
> memhotplug.c
> index 34e40b733f9a..4fc886cd5586 100644
> --- a/drivers/xen/xen-acpi-memhotplug.c
> +++ b/drivers/xen/xen-acpi-memhotplug.c
> @@ -117,8 +117,8 @@ acpi_memory_get_resource(struct acpi_resource
> *resource, void *context)
> list_for_each_entry(info, &mem_device->res_list, list) {
> if ((info->caching == address64.info.mem.caching) &&
> (info->write_protect ==
> address64.info.mem.write_protect) &&
> - (info->start_addr + info->length == address64.minimum)) {
> - info->length += address64.address_length;
> + (info->start_addr + info->length ==
> address64.address.minimum)) {
> + info->length += address64.address.address_length;
> return AE_OK;
> }
> }
> @@ -130,8 +130,8 @@ acpi_memory_get_resource(struct acpi_resource
> *resource, void *context)
> INIT_LIST_HEAD(&new->list);
> new->caching = address64.info.mem.caching;
> new->write_protect = address64.info.mem.write_protect;
> - new->start_addr = address64.minimum;
> - new->length = address64.address_length;
> + new->start_addr = address64.address.minimum;
> + new->length = address64.address.address_length;
> list_add_tail(&new->list, &mem_device->res_list);
>
> return AE_OK;
> diff --git a/include/acpi/acrestyp.h b/include/acpi/acrestyp.h index
> eb760ca0b2e0..0b75e01212c7 100644
> --- a/include/acpi/acrestyp.h
> +++ b/include/acpi/acrestyp.h
> @@ -305,43 +305,51 @@ struct acpi_resource_source {
> u8 max_address_fixed; \
> union acpi_resource_attribute info;
>
> -struct acpi_resource_address {
> -ACPI_RESOURCE_ADDRESS_COMMON};
> -
> -struct acpi_resource_address16 {
> - ACPI_RESOURCE_ADDRESS_COMMON u16 granularity;
> +struct acpi_address16_attribute {
> + u16 granularity;
> u16 minimum;
> u16 maximum;
> u16 translation_offset;
> u16 address_length;
> - struct acpi_resource_source resource_source;
> };
>
> -struct acpi_resource_address32 {
> - ACPI_RESOURCE_ADDRESS_COMMON u32 granularity;
> +struct acpi_address32_attribute {
> + u32 granularity;
> u32 minimum;
> u32 maximum;
> u32 translation_offset;
> u32 address_length;
> - struct acpi_resource_source resource_source;
> };
>
> -struct acpi_resource_address64 {
> - ACPI_RESOURCE_ADDRESS_COMMON u64 granularity;
> +struct acpi_address64_attribute {
> + u64 granularity;
> u64 minimum;
> u64 maximum;
> u64 translation_offset;
> u64 address_length;
> +};
> +
> +struct acpi_resource_address {
> +ACPI_RESOURCE_ADDRESS_COMMON};
> +
> +struct acpi_resource_address16 {
> + ACPI_RESOURCE_ADDRESS_COMMON struct
> acpi_address16_attribute address;
> + struct acpi_resource_source resource_source; };
> +
> +struct acpi_resource_address32 {
> + ACPI_RESOURCE_ADDRESS_COMMON struct
> acpi_address32_attribute address;
> + struct acpi_resource_source resource_source; };
> +
> +struct acpi_resource_address64 {
> + ACPI_RESOURCE_ADDRESS_COMMON struct
> acpi_address64_attribute address;
> struct acpi_resource_source resource_source; };
>
> struct acpi_resource_extended_address64 {
> ACPI_RESOURCE_ADDRESS_COMMON u8 revision_ID;
> - u64 granularity;
> - u64 minimum;
> - u64 maximum;
> - u64 translation_offset;
> - u64 address_length;
> + struct acpi_address64_attribute address;
> u64 type_specific;
> };
>
> --
> 1.7.10.4