LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug
@ 2015-01-28 10:57 Jiang Liu
  2015-01-28 10:57 ` [Patch v2 01/22] ACPICA: Resources: Provide common part for struct acpi_resource_address structures Jiang Liu
                   ` (21 more replies)
  0 siblings, 22 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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-19 try to share the common data structure resource_list_entry
between PCI and ACPI. It may also be shared with PNP too.

Patch 20-22 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

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+

Thanks,
Gerry

Jiang Liu (13):
  ACPI: Fix a bug in parsing ACPI Memroy24 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/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                 |  296 ++++++++++-------------------
 arch/x86/pci/bus_numa.c             |    4 +-
 arch/x86/pci/common.c               |   30 ++-
 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            |    6 +-
 drivers/acpi/acpi_memhotplug.c      |    8 +-
 drivers/acpi/acpi_platform.c        |    2 +-
 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               |  225 ++++++++++++++++++++++
 drivers/acpi/pci_irq.c              |    9 +-
 drivers/acpi/pci_root.c             |    9 +-
 drivers/acpi/processor_core.c       |  123 +++++++++++-
 drivers/acpi/resource.c             |  349 +++++++++++++++++++++--------------
 drivers/char/hpet.c                 |    4 +-
 drivers/dma/acpi-dma.c              |    8 +-
 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, 964 insertions(+), 531 deletions(-)
 create mode 100644 drivers/acpi/ioapic.c
 create mode 100644 include/linux/resource_ext.h

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 01/22] ACPICA: Resources: Provide common part for struct acpi_resource_address structures.
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 02/22] ACPI: Remove redundant check in function acpi_dev_resource_address_space() Jiang Liu
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Tony Luck, Fenghua Yu, Ingo Molnar,
	H. Peter Anvin, x86, Len Brown, Robert Moore, Clemens Ladisch,
	Arnd Bergmann, Greg Kroah-Hartman, K. Y. Srinivasan,
	Haiyang Zhang, Konrad Rzeszutek Wilk, Boris Ostrovsky,
	David Vrabel
  Cc: linux-kernel, linux-pci, linux-acpi, Jiang Liu, linux-ia64,
	devel, devel, xen-devel

From: Lv Zheng <lv.zheng@intel.com>

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 <tglx@linutronix.de>
Original-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 02/22] ACPI: Remove redundant check in function acpi_dev_resource_address_space()
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
  2015-01-28 10:57 ` [Patch v2 01/22] ACPICA: Resources: Provide common part for struct acpi_resource_address structures Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 03/22] ACPI: Implement proper length checks for mem resources Jiang Liu
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

The ACPI type is checked in acpi_resource_to_address64() anyway.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 03/22] ACPI: Implement proper length checks for mem resources
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
  2015-01-28 10:57 ` [Patch v2 01/22] ACPICA: Resources: Provide common part for struct acpi_resource_address structures Jiang Liu
  2015-01-28 10:57 ` [Patch v2 02/22] ACPI: Remove redundant check in function acpi_dev_resource_address_space() Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 04/22] ACPI: Use the length check for io resources as well Jiang Liu
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

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 <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 04/22] ACPI: Use the length check for io resources as well
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (2 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 03/22] ACPI: Implement proper length checks for mem resources Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 05/22] ACPI: Let the parser return false for disabled resources Jiang Liu
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

Also apply length check to IO resources.

[Jiang] Remove enforcement that resource starting address must be
non-zero.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 05/22] ACPI: Let the parser return false for disabled resources
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (3 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 04/22] ACPI: Use the length check for io resources as well Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 06/22] ACPI: Unify the parsing of address_space and ext_address_space Jiang Liu
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

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 <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 06/22] ACPI: Unify the parsing of address_space and ext_address_space
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (4 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 05/22] ACPI: Let the parser return false for disabled resources Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 07/22] ACPI: Move the window flag logic to the combined parser Jiang Liu
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

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 <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 07/22] ACPI: Move the window flag logic to the combined parser
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (5 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 06/22] ACPI: Unify the parsing of address_space and ext_address_space Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 08/22] ACPI: Add prefetch decoding to the address space parser Jiang Liu
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

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 <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 08/22] ACPI: Add prefetch decoding to the address space parser
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (6 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 07/22] ACPI: Move the window flag logic to the combined parser Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource Jiang Liu
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu

From: Thomas Gleixner <tglx@linutronix.de>

Add support of PREFETCH attributre to ACPI address space and extended
address space parser.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (7 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 08/22] ACPI: Add prefetch decoding to the address space parser Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 23:15   ` Bjorn Helgaas
  2015-01-28 10:57 ` [Patch v2 10/22] ACPI: Normalize return value of resource parser functions Jiang Liu
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 10/22] ACPI: Normalize return value of resource parser functions
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (8 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 11/22] ACPI: Set flag IORESOURCE_UNSET for unassigned resources Jiang Liu
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 11/22] ACPI: Set flag IORESOURCE_UNSET for unassigned resources
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (9 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 10/22] ACPI: Normalize return value of resource parser functions Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 12/22] ACPI: Enforce stricter checks for address space descriptors Jiang Liu
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

Also set flag IORESOURCE_UNSET for unassigned resource in addition to
IORESOURCE_DISABLED to mark resource as unassigned.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 12/22] ACPI: Enforce stricter checks for address space descriptors
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (10 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 11/22] ACPI: Set flag IORESOURCE_UNSET for unassigned resources Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 13/22] ACPI: Return translation offset when parsing ACPI address space resources Jiang Liu
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

Enforce stricter checks for address space descriptors according to
ACPI spec.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 13/22] ACPI: Return translation offset when parsing ACPI address space resources
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (11 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 12/22] ACPI: Enforce stricter checks for address space descriptors Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 14/22] ACPI: Translate resource into master side address for bridge window resources Jiang Liu
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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 <yinghai@kernel.org>.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 14/22] ACPI: Translate resource into master side address for bridge window resources
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (12 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 13/22] ACPI: Return translation offset when parsing ACPI address space resources Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 15/22] ACPI: Add field offset to struct resource_list_entry Jiang Liu
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 15/22] ACPI: Add field offset to struct resource_list_entry
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (13 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 14/22] ACPI: Translate resource into master side address for bridge window resources Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 16/22] ACPI: Introduce helper function acpi_dev_filter_resource_type() Jiang Liu
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 16/22] ACPI: Introduce helper function acpi_dev_filter_resource_type()
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (14 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 15/22] ACPI: Add field offset to struct resource_list_entry Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core Jiang Liu
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi

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 <jiang.liu@linux.intel.com>
---
 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (15 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 16/22] ACPI: Introduce helper function acpi_dev_filter_resource_type() Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-02-05  1:56   ` Vinod Koul
  2015-01-28 10:57 ` [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation Jiang Liu
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown, Dan Williams, Vinod Koul,
	Jiang Liu, Andrew Morton, Vivek Goyal, Thierry Reding,
	Mike Travis
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, dmaengine

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. Sp move struct resource_list_entry
from ACPI into resource core, so 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 <jiang.liu@linux.intel.com>
---
 drivers/acpi/acpi_lpss.c     |    6 ++--
 drivers/acpi/acpi_platform.c |    2 +-
 drivers/acpi/resource.c      |   13 +++----
 drivers/dma/acpi-dma.c       |    8 ++---
 include/linux/acpi.h         |   12 +------
 include/linux/resource_ext.h |   77 ++++++++++++++++++++++++++++++++++++++++++
 kernel/resource.c            |   25 ++++++++++++++
 7 files changed, 115 insertions(+), 28 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..39b548dba70b 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -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..238e32b9cbb0 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -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..f7648205416e 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);
 
@@ -466,14 +461,14 @@ static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,
 {
 	struct resource_list_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;
 }
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
index de361a156b34..1ce84abe0924 100644
--- a/drivers/dma/acpi-dma.c
+++ b/drivers/dma/acpi-dma.c
@@ -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..ea385e513ab1
--- /dev/null
+++ b/include/linux/resource_ext.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015, Intel Corporation
+ * Author: Jiang Liu <jiang.liu@linux.intel.com>
+ *
+ * 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_list_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_list_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_list_entry *entry,
+				     struct list_head *head)
+{
+	list_add(&entry->node, head);
+}
+
+static inline void resource_list_add_tail(struct resource_list_entry *entry,
+					  struct list_head *head)
+{
+	list_add_tail(&entry->node, head);
+}
+
+static inline void resource_list_del(struct resource_list_entry *entry)
+{
+	list_del(&entry->node);
+}
+
+static inline void resource_list_free_entry(struct resource_list_entry *entry)
+{
+	kfree(entry);
+}
+
+static inline void
+resource_list_destroy_entry(struct resource_list_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..d8b3b0e9658a 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_list_entry *resource_list_create_entry(struct resource *res,
+						       size_t extra_size)
+{
+	struct resource_list_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_list_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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (16 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 13:46   ` Will Deacon
  2015-01-28 23:34   ` Bjorn Helgaas
  2015-01-28 10:57 ` [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation Jiang Liu
                   ` (3 subsequent siblings)
  21 siblings, 2 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Russell King, Ingo Molnar,
	H. Peter Anvin, x86, Will Deacon, Tanmay Inamdar, Michal Simek,
	Sören Brinkmann, Yijing Wang, Murali Karicheri, Jiang Liu,
	Srikanth Thokala
  Cc: Tony Luck, linux-kernel, linux-pci, linux-acpi, Russell King,
	linux-arm-kernel

Use common resource list management data structure and interfaces
instead of private implementation.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 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..968b03cb6376 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_list_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..6785af30ed39 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_list_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..c850c48d81d2 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_list_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..3ea13883e6a5 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_list_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_list_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..16d5d6eeb35a 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_list_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..e335b834f950 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_list_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..253e993a111f 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_list_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..df6a40932aa0 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_list_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_list_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..6aa40d62cdab 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_list_entry */
 	void (*release_fn)(struct pci_host_bridge *);
 	void *release_data;
 };
-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (17 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 23:37   ` Bjorn Helgaas
  2015-01-28 23:51   ` Bjorn Helgaas
  2015-01-28 10:57 ` [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources Jiang Liu
                   ` (2 subsequent siblings)
  21 siblings, 2 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Ingo Molnar, H. Peter Anvin, x86
  Cc: Jiang Liu, Tony Luck, linux-kernel, linux-pci, linux-acpi

Use common ACPI resource discovery interfaces to simplify PCI host bridge
resource enumeration.

It also fixes the issue discovered by Thomas that function setup_resource()
incorrectly validates IO port resources against iomem_resource.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/pci/acpi.c |  296 ++++++++++++++++-----------------------------------
 1 file changed, 94 insertions(+), 202 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index bb98afd0591e..3404ea703ecc 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,130 +215,44 @@ 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;
-
-	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;
-	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		flags = IORESOURCE_IO;
-	} 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, (u64)iomem_resource.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_list_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 [%#llx-%#llx] (ignored, not CPU addressable)\n",
+				 (unsigned long long)res1->start,
+				 (unsigned long long)res1->end);
+			free = true;
+			goto next;
+		} else if (res1->end != end) {
+			dev_info(dev, "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				 (unsigned long long)res1->start,
+				 (unsigned long long)res1->end,
+				 (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;
 
@@ -353,118 +264,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_list_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_list_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_list_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)
@@ -473,6 +358,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_list_entry *res_entry;
+	LIST_HEAD(crs_res);
 	LIST_HEAD(resources);
 	struct pci_bus *bus;
 	struct pci_sysdata *sd;
@@ -520,18 +407,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);
 		}
 
@@ -546,8 +437,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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (18 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 23:38   ` Bjorn Helgaas
  2015-01-28 10:57 ` [Patch v2 21/22] ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug Jiang Liu
  2015-01-28 10:57 ` [Patch v2 22/22] x86/irq, ACPI: Implement ACPI driver to support " Jiang Liu
  21 siblings, 1 reply; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Ingo Molnar, H. Peter Anvin, x86,
	Len Brown
  Cc: Jiang Liu, Tony Luck, linux-kernel, linux-pci, linux-acpi

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 c03b3b0738a56cf283b0d05256988d5e3c8bd719 ("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 <david.vrabel@citrix.com> 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 <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/pci_x86.h |    2 --
 arch/x86/pci/common.c          |   30 ++++++++++++++++++++++++++++--
 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(+), 28 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..99f15ed19f38 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -497,6 +497,25 @@ void __init pcibios_set_cache_line_size(void)
 	}
 }
 
+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 +528,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;
 }
 
@@ -669,8 +691,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
 void pcibios_disable_device (struct pci_dev *dev)
 {
-	if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
-		pcibios_disable_irq(dev);
+	/*
+	 * 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.
+	 */
 }
 
 int pci_ext_cfg_avail(void)
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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 21/22] ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (19 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  2015-01-28 10:57 ` [Patch v2 22/22] x86/irq, ACPI: Implement ACPI driver to support " Jiang Liu
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, Jiang Liu,
	Konrad Rzeszutek Wilk, Joerg Roedel, Greg Kroah-Hartman,
	Benjamin Herrenschmidt, Randy Dunlap

From: Yinghai Lu <yinghai@kernel.org>

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 <yinghai@kernel.org>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Len Brown <lenb@kernel.org>
Link: http://lkml.kernel.org/r/1414387308-27148-8-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 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 <achiang@hp.com>
  *	- Unified x86/ia64 implementations
+ *
+ * I/O APIC hotplug support
+ *	Yinghai Lu <yinghai@kernel.org>
+ *	Jiang Liu <jiang.liu@intel.com>
  */
 #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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [Patch v2 22/22] x86/irq, ACPI: Implement ACPI driver to support IOAPIC hotplug
  2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
                   ` (20 preceding siblings ...)
  2015-01-28 10:57 ` [Patch v2 21/22] ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug Jiang Liu
@ 2015-01-28 10:57 ` Jiang Liu
  21 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-28 10:57 UTC (permalink / raw)
  To: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown
  Cc: Jiang Liu, Tony Luck, x86, linux-kernel, linux-pci, linux-acpi,
	Konrad Rzeszutek Wilk, Joerg Roedel, Greg Kroah-Hartman,
	Benjamin Herrenschmidt, Randy Dunlap

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 <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Len Brown <lenb@kernel.org>
Link: http://lkml.kernel.org/r/1414387308-27148-19-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 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 <yinghai@kernel.org>
+ *	Jiang Liu <jiang.liu@intel.com>
+ */
+
+/*
+ * 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


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation
  2015-01-28 10:57 ` [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation Jiang Liu
@ 2015-01-28 13:46   ` Will Deacon
  2015-01-28 23:34   ` Bjorn Helgaas
  1 sibling, 0 replies; 32+ messages in thread
From: Will Deacon @ 2015-01-28 13:46 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Russell King, Ingo Molnar,
	H. Peter Anvin, x86, Tanmay Inamdar, Michal Simek,
	Sören Brinkmann, Yijing Wang, Murali Karicheri,
	Srikanth Thokala, Tony Luck, linux-kernel, linux-pci, linux-acpi,
	Russell King, linux-arm-kernel

On Wed, Jan 28, 2015 at 10:57:36AM +0000, Jiang Liu wrote:
> Use common resource list management data structure and interfaces
> instead of private implementation.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  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(-)

The arch/arm/ and drivers/pci/host/pci-host-generic.c bits look fine to
me:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource
  2015-01-28 10:57 ` [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource Jiang Liu
@ 2015-01-28 23:15   ` Bjorn Helgaas
  0 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2015-01-28 23:15 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Len Brown, Tony Luck, x86, linux-kernel, linux-pci,
	linux-acpi

"Memory24", not "Memroy24", in subject.

On Wed, Jan 28, 2015 at 06:57:27PM +0800, Jiang Liu wrote:
> 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 <jiang.liu@linux.intel.com>
> ---
>  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
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation
  2015-01-28 10:57 ` [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation Jiang Liu
  2015-01-28 13:46   ` Will Deacon
@ 2015-01-28 23:34   ` Bjorn Helgaas
  1 sibling, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2015-01-28 23:34 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Russell King, Ingo Molnar, H. Peter Anvin, x86,
	Will Deacon, Tanmay Inamdar, Michal Simek, Sören Brinkmann,
	Yijing Wang, Murali Karicheri, Srikanth Thokala, Tony Luck,
	linux-kernel, linux-pci, linux-acpi, Russell King,
	linux-arm-kernel

On Wed, Jan 28, 2015 at 06:57:36PM +0800, Jiang Liu wrote:
> Use common resource list management data structure and interfaces
> instead of private implementation.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

> ---
>  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..968b03cb6376 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_list_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..6785af30ed39 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_list_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..c850c48d81d2 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_list_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..3ea13883e6a5 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_list_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_list_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..16d5d6eeb35a 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_list_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..e335b834f950 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_list_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..253e993a111f 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_list_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..df6a40932aa0 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_list_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_list_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..6aa40d62cdab 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_list_entry */
>  	void (*release_fn)(struct pci_host_bridge *);
>  	void *release_data;
>  };
> -- 
> 1.7.10.4
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
  2015-01-28 10:57 ` [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation Jiang Liu
@ 2015-01-28 23:37   ` Bjorn Helgaas
  2015-01-29  3:00     ` Jiang Liu
  2015-01-28 23:51   ` Bjorn Helgaas
  1 sibling, 1 reply; 32+ messages in thread
From: Bjorn Helgaas @ 2015-01-28 23:37 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Ingo Molnar, H. Peter Anvin, x86, Tony Luck,
	linux-kernel, linux-pci, linux-acpi

On Wed, Jan 28, 2015 at 06:57:37PM +0800, Jiang Liu wrote:
> Use common ACPI resource discovery interfaces to simplify PCI host bridge
> resource enumeration.
> 
> It also fixes the issue discovered by Thomas that function setup_resource()
> incorrectly validates IO port resources against iomem_resource.

Is it possible to split this bug fix into its own separate patch?  Mixing
things together makes git archaeology harder because it hides tiny bug
fixes inside big changes.

> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  arch/x86/pci/acpi.c |  296 ++++++++++++++++-----------------------------------
>  1 file changed, 94 insertions(+), 202 deletions(-)
> 
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index bb98afd0591e..3404ea703ecc 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,130 +215,44 @@ 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;
> -
> -	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;
> -	} else if (addr.resource_type == ACPI_IO_RANGE) {
> -		flags = IORESOURCE_IO;
> -	} 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, (u64)iomem_resource.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_list_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 [%#llx-%#llx] (ignored, not CPU addressable)\n",
> +				 (unsigned long long)res1->start,
> +				 (unsigned long long)res1->end);
> +			free = true;
> +			goto next;
> +		} else if (res1->end != end) {
> +			dev_info(dev, "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
> +				 (unsigned long long)res1->start,
> +				 (unsigned long long)res1->end,
> +				 (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;
>  
> @@ -353,118 +264,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_list_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_list_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_list_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)
> @@ -473,6 +358,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_list_entry *res_entry;
> +	LIST_HEAD(crs_res);
>  	LIST_HEAD(resources);
>  	struct pci_bus *bus;
>  	struct pci_sysdata *sd;
> @@ -520,18 +407,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);
>  		}
>  
> @@ -546,8 +437,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
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources
  2015-01-28 10:57 ` [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources Jiang Liu
@ 2015-01-28 23:38   ` Bjorn Helgaas
  0 siblings, 0 replies; 32+ messages in thread
From: Bjorn Helgaas @ 2015-01-28 23:38 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Ingo Molnar, H. Peter Anvin, x86, Len Brown, Tony Luck,
	linux-kernel, linux-pci, linux-acpi

On Wed, Jan 28, 2015 at 06:57:38PM +0800, Jiang Liu wrote:
> 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 c03b3b0738a56cf283b0d05256988d5e3c8bd719 ("x86, irq, mpparse:

Cosmetic: please use the conventional 12-char SHA1 as you did below.

> 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.

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
  2015-01-28 10:57 ` [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation Jiang Liu
  2015-01-28 23:37   ` Bjorn Helgaas
@ 2015-01-28 23:51   ` Bjorn Helgaas
  2015-01-29  3:11     ` Jiang Liu
  1 sibling, 1 reply; 32+ messages in thread
From: Bjorn Helgaas @ 2015-01-28 23:51 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Ingo Molnar, H. Peter Anvin, x86, Tony Luck,
	linux-kernel, linux-pci, linux-acpi

On Wed, Jan 28, 2015 at 06:57:37PM +0800, Jiang Liu wrote:
> Use common ACPI resource discovery interfaces to simplify PCI host bridge
> resource enumeration.
> 
> It also fixes the issue discovered by Thomas that function setup_resource()
> incorrectly validates IO port resources against iomem_resource.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

Nice cleanups, thanks.  A few more trival comments below.

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

> ---
>  arch/x86/pci/acpi.c |  296 ++++++++++++++++-----------------------------------
>  1 file changed, 94 insertions(+), 202 deletions(-)
> 
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index bb98afd0591e..3404ea703ecc 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,130 +215,44 @@ 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;
> -
> -	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;
> -	} else if (addr.resource_type == ACPI_IO_RANGE) {
> -		flags = IORESOURCE_IO;
> -	} 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, (u64)iomem_resource.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_list_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 [%#llx-%#llx] (ignored, not CPU addressable)\n",
> +				 (unsigned long long)res1->start,
> +				 (unsigned long long)res1->end);

It looks like you have a struct resource now, so you should use %pR instead
of printing ->start and ->end by hand.

> +			free = true;
> +			goto next;
> +		} else if (res1->end != end) {
> +			dev_info(dev, "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
> +				 (unsigned long long)res1->start,
> +				 (unsigned long long)res1->end,
> +				 (unsigned long long)end + 1,
> +				 (unsigned long long)res1->end);

Looks like you can use %pR here too (for the first one, not the second
unaddressable range).

> +			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;
>  
> @@ -353,118 +264,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_list_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_list_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_list_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");

Most people don't bother with periods at the end of messages like these.

> +	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)
> @@ -473,6 +358,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_list_entry *res_entry;
> +	LIST_HEAD(crs_res);
>  	LIST_HEAD(resources);
>  	struct pci_bus *bus;
>  	struct pci_sysdata *sd;
> @@ -520,18 +407,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);
>  		}
>  
> @@ -546,8 +437,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
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
  2015-01-28 23:37   ` Bjorn Helgaas
@ 2015-01-29  3:00     ` Jiang Liu
  0 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-29  3:00 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Ingo Molnar, H. Peter Anvin, x86, Tony Luck,
	linux-kernel, linux-pci, linux-acpi

On 2015/1/29 7:37, Bjorn Helgaas wrote:
> On Wed, Jan 28, 2015 at 06:57:37PM +0800, Jiang Liu wrote:
>> Use common ACPI resource discovery interfaces to simplify PCI host bridge
>> resource enumeration.
>>
>> It also fixes the issue discovered by Thomas that function setup_resource()
>> incorrectly validates IO port resources against iomem_resource.
> 
> Is it possible to split this bug fix into its own separate patch?  Mixing
> things together makes git archaeology harder because it hides tiny bug
> fixes inside big changes.
Hi Bjorn,
	I will split out a patch to fix the issue in next version.
Thanks!
Gerry

> 
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>  arch/x86/pci/acpi.c |  296 ++++++++++++++++-----------------------------------
>>  1 file changed, 94 insertions(+), 202 deletions(-)
>>
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index bb98afd0591e..3404ea703ecc 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,130 +215,44 @@ 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;
>> -
>> -	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;
>> -	} else if (addr.resource_type == ACPI_IO_RANGE) {
>> -		flags = IORESOURCE_IO;
>> -	} 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, (u64)iomem_resource.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_list_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 [%#llx-%#llx] (ignored, not CPU addressable)\n",
>> +				 (unsigned long long)res1->start,
>> +				 (unsigned long long)res1->end);
>> +			free = true;
>> +			goto next;
>> +		} else if (res1->end != end) {
>> +			dev_info(dev, "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
>> +				 (unsigned long long)res1->start,
>> +				 (unsigned long long)res1->end,
>> +				 (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;
>>  
>> @@ -353,118 +264,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_list_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_list_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_list_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)
>> @@ -473,6 +358,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_list_entry *res_entry;
>> +	LIST_HEAD(crs_res);
>>  	LIST_HEAD(resources);
>>  	struct pci_bus *bus;
>>  	struct pci_sysdata *sd;
>> @@ -520,18 +407,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);
>>  		}
>>  
>> @@ -546,8 +437,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
>>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
  2015-01-28 23:51   ` Bjorn Helgaas
@ 2015-01-29  3:11     ` Jiang Liu
  0 siblings, 0 replies; 32+ messages in thread
From: Jiang Liu @ 2015-01-29  3:11 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Rafael J. Wysocki, Thomas Gleixner, Yinghai Lu, Borislav Petkov,
	Lv Zheng, Ingo Molnar, H. Peter Anvin, x86, Tony Luck,
	linux-kernel, linux-pci, linux-acpi

On 2015/1/29 7:51, Bjorn Helgaas wrote:
> On Wed, Jan 28, 2015 at 06:57:37PM +0800, Jiang Liu wrote:
>> Use common ACPI resource discovery interfaces to simplify PCI host bridge
>> resource enumeration.
>>
>> It also fixes the issue discovered by Thomas that function setup_resource()
>> incorrectly validates IO port resources against iomem_resource.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> 
> Nice cleanups, thanks.  A few more trival comments below.
> 
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Thanks, Bjorn. Will fix following issues in next version.

> 
>> ---
>>  arch/x86/pci/acpi.c |  296 ++++++++++++++++-----------------------------------
>>  1 file changed, 94 insertions(+), 202 deletions(-)
>>
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index bb98afd0591e..3404ea703ecc 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,130 +215,44 @@ 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;
>> -
>> -	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;
>> -	} else if (addr.resource_type == ACPI_IO_RANGE) {
>> -		flags = IORESOURCE_IO;
>> -	} 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, (u64)iomem_resource.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_list_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 [%#llx-%#llx] (ignored, not CPU addressable)\n",
>> +				 (unsigned long long)res1->start,
>> +				 (unsigned long long)res1->end);
> 
> It looks like you have a struct resource now, so you should use %pR instead
> of printing ->start and ->end by hand.
> 
>> +			free = true;
>> +			goto next;
>> +		} else if (res1->end != end) {
>> +			dev_info(dev, "host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
>> +				 (unsigned long long)res1->start,
>> +				 (unsigned long long)res1->end,
>> +				 (unsigned long long)end + 1,
>> +				 (unsigned long long)res1->end);
> 
> Looks like you can use %pR here too (for the first one, not the second
> unaddressable range).
> 
>> +			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;
>>  
>> @@ -353,118 +264,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_list_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_list_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_list_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");
> 
> Most people don't bother with periods at the end of messages like these.
> 
>> +	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)
>> @@ -473,6 +358,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_list_entry *res_entry;
>> +	LIST_HEAD(crs_res);
>>  	LIST_HEAD(resources);
>>  	struct pci_bus *bus;
>>  	struct pci_sysdata *sd;
>> @@ -520,18 +407,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);
>>  		}
>>  
>> @@ -546,8 +437,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
>>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core
  2015-01-28 10:57 ` [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core Jiang Liu
@ 2015-02-05  1:56   ` Vinod Koul
  0 siblings, 0 replies; 32+ messages in thread
From: Vinod Koul @ 2015-02-05  1:56 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Rafael J. Wysocki, Thomas Gleixner, Bjorn Helgaas, Yinghai Lu,
	Borislav Petkov, Lv Zheng, Len Brown, Dan Williams,
	Andrew Morton, Vivek Goyal, Thierry Reding, Mike Travis,
	Tony Luck, x86, linux-kernel, linux-pci, linux-acpi, dmaengine

On Wed, Jan 28, 2015 at 06:57:35PM +0800, Jiang Liu wrote:
> 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. Sp move struct resource_list_entry
Typo				    ^^
> from ACPI into resource core, so 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 <jiang.liu@linux.intel.com>
> ---
>  drivers/acpi/acpi_lpss.c     |    6 ++--
>  drivers/acpi/acpi_platform.c |    2 +-
>  drivers/acpi/resource.c      |   13 +++----
>  drivers/dma/acpi-dma.c       |    8 ++---
For dmaengine:

Acked-by: Vinod Koul <vinod.koul@intel.com>

-- 
~Vinod


^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2015-02-05  1:58 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-28 10:57 [Patch v2 00/22] Improve ACPI resource parsing interfaces and enable IOAPIC hotplug Jiang Liu
2015-01-28 10:57 ` [Patch v2 01/22] ACPICA: Resources: Provide common part for struct acpi_resource_address structures Jiang Liu
2015-01-28 10:57 ` [Patch v2 02/22] ACPI: Remove redundant check in function acpi_dev_resource_address_space() Jiang Liu
2015-01-28 10:57 ` [Patch v2 03/22] ACPI: Implement proper length checks for mem resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 04/22] ACPI: Use the length check for io resources as well Jiang Liu
2015-01-28 10:57 ` [Patch v2 05/22] ACPI: Let the parser return false for disabled resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 06/22] ACPI: Unify the parsing of address_space and ext_address_space Jiang Liu
2015-01-28 10:57 ` [Patch v2 07/22] ACPI: Move the window flag logic to the combined parser Jiang Liu
2015-01-28 10:57 ` [Patch v2 08/22] ACPI: Add prefetch decoding to the address space parser Jiang Liu
2015-01-28 10:57 ` [Patch v2 09/22] ACPI: Fix a bug in parsing ACPI Memroy24 resource Jiang Liu
2015-01-28 23:15   ` Bjorn Helgaas
2015-01-28 10:57 ` [Patch v2 10/22] ACPI: Normalize return value of resource parser functions Jiang Liu
2015-01-28 10:57 ` [Patch v2 11/22] ACPI: Set flag IORESOURCE_UNSET for unassigned resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 12/22] ACPI: Enforce stricter checks for address space descriptors Jiang Liu
2015-01-28 10:57 ` [Patch v2 13/22] ACPI: Return translation offset when parsing ACPI address space resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 14/22] ACPI: Translate resource into master side address for bridge window resources Jiang Liu
2015-01-28 10:57 ` [Patch v2 15/22] ACPI: Add field offset to struct resource_list_entry Jiang Liu
2015-01-28 10:57 ` [Patch v2 16/22] ACPI: Introduce helper function acpi_dev_filter_resource_type() Jiang Liu
2015-01-28 10:57 ` [Patch v2 17/22] resources: Move struct resource_list_entry from ACPI into resource core Jiang Liu
2015-02-05  1:56   ` Vinod Koul
2015-01-28 10:57 ` [Patch v2 18/22] PCI: Use common resource list management code instead of private implementation Jiang Liu
2015-01-28 13:46   ` Will Deacon
2015-01-28 23:34   ` Bjorn Helgaas
2015-01-28 10:57 ` [Patch v2 19/22] x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation Jiang Liu
2015-01-28 23:37   ` Bjorn Helgaas
2015-01-29  3:00     ` Jiang Liu
2015-01-28 23:51   ` Bjorn Helgaas
2015-01-29  3:11     ` Jiang Liu
2015-01-28 10:57 ` [Patch v2 20/22] x86/PCI: Refine the way to release PCI IRQ resources Jiang Liu
2015-01-28 23:38   ` Bjorn Helgaas
2015-01-28 10:57 ` [Patch v2 21/22] ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug Jiang Liu
2015-01-28 10:57 ` [Patch v2 22/22] x86/irq, ACPI: Implement ACPI driver to support " Jiang Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).