linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core
@ 2015-05-14  8:56 Jiang Liu
  2015-05-14  8:56 ` [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo, Yijing Wang
  Cc: Jiang Liu, Lv Zheng, lenb @ kernel . org, LKML, linux-pci,
	linux-acpi, x86 @ kernel . org, linux-arm-kernel

This patch set consolidates common code to support ACPI PCI root on x86
and IA64 platforms into ACPI core, to reproduce duplicated code and
simplify maintenance. The common code should also used to support PCI
host bridge on ARM64 too, but I'm lacking of knowledge about PCIe host
bridge implementation details on ARM64, so please help to review whether
this is suitable for ARM64 too.

It passes Fengguang's 0day test suite and has been tested on two IA64
platforms and one x86 platform.

It's based on latest mainstream kernel and available at:
https://github.com/jiangliu/linux.git acpi_pci_root_v3

V2->V3:
1. Move memory allocation/free from ACPI core into arch
2. Kill the field 'segment' in struct pci_root_info on x86

Thanks!
Gerry

Jiang Liu (7):
  ACPI/PCI: Enhance ACPI core to support sparse IO space
  ia64/PCI/ACPI: Use common ACPI resource parsing interface for host
    bridge
  ia64/PCI: Use common struct resource_entry to replace struct
    iospace_resource
  x86/PCI: Rename struct pci_sysdata as struct pci_controller
  PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  x86/PCI/ACPI: Use common interface to support PCI host bridge
  ia64/PCI/ACPI: Use common interface to support PCI host bridge

 arch/ia64/include/asm/pci.h   |    5 -
 arch/ia64/pci/pci.c           |  364 +++++++++++------------------------------
 arch/x86/include/asm/pci.h    |   13 +-
 arch/x86/include/asm/pci_64.h |    4 +-
 arch/x86/pci/acpi.c           |  294 ++++++++++-----------------------
 arch/x86/pci/common.c         |    2 +-
 drivers/acpi/pci_root.c       |  200 ++++++++++++++++++++++
 drivers/acpi/resource.c       |    9 +-
 include/linux/ioport.h        |    1 +
 include/linux/pci-acpi.h      |   23 +++
 10 files changed, 421 insertions(+), 494 deletions(-)

-- 
1.7.10.4


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

* [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  2015-05-22 13:35   ` Hanjun Guo
  2015-05-14  8:56 ` [Patch v3 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Len Brown, Vivek Goyal, Thierry Reding,
	Jakub Sitnicki
  Cc: Jiang Liu, Lv Zheng, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel

Enhance ACPI resource parsing interfaces to support sparse IO space,
which will be used to share common code between x86 and IA64 later.

Tested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/resource.c |    9 ++++++---
 include/linux/ioport.h  |    1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 8244f013f210..fdcc73dad2c1 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -123,7 +123,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)
+				      u8 io_decode, u8 translation_type)
 {
 	res->flags = IORESOURCE_IO;
 
@@ -135,6 +135,8 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
 
 	if (io_decode == ACPI_DECODE_16)
 		res->flags |= IORESOURCE_IO_16BIT_ADDR;
+	if (translation_type == ACPI_SPARSE_TRANSLATION)
+		res->flags |= IORESOURCE_IO_SPARSE;
 }
 
 static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
@@ -142,7 +144,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);
+	acpi_dev_ioresource_flags(res, len, io_decode, 0);
 }
 
 /**
@@ -227,7 +229,8 @@ static bool acpi_decode_space(struct resource_win *win,
 		acpi_dev_memresource_flags(res, len, wp);
 		break;
 	case ACPI_IO_RANGE:
-		acpi_dev_ioresource_flags(res, len, iodec);
+		acpi_dev_ioresource_flags(res, len, iodec,
+					  addr->info.io.translation_type);
 		break;
 	case ACPI_BUS_NUMBER_RANGE:
 		res->flags = IORESOURCE_BUS;
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 388e3ae94f7a..24bea087e7af 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -94,6 +94,7 @@ struct resource {
 /* PnP I/O specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_IO_16BIT_ADDR	(1<<0)
 #define IORESOURCE_IO_FIXED		(1<<1)
+#define IORESOURCE_IO_SPARSE		(1<<2)
 
 /* PCI ROM control bits (IORESOURCE_BITS) */
 #define IORESOURCE_ROM_ENABLE		(1<<0)	/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
-- 
1.7.10.4


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

* [Patch v3 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
  2015-05-14  8:56 ` [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  2015-05-22 13:42   ` Hanjun Guo
  2015-05-14  8:56 ` [Patch v3 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Tony Luck, Fenghua Yu, Jiang Liu, Yinghai Lu
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel, linux-ia64

Use common ACPI resource parsing interface to parse ACPI resources for
PCI host bridge, so we could share more code between IA64 and x86.
Later we will consolidate arch specific implementations into ACPI core.

Tested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/ia64/pci/pci.c |  414 ++++++++++++++++++++++++---------------------------
 1 file changed, 193 insertions(+), 221 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index d4e162d35b34..23689d4c37ae 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -115,29 +115,12 @@ struct pci_ops pci_root_ops = {
 	.write = pci_write,
 };
 
-/* Called by ACPI when it finds a new root bus.  */
-
-static struct pci_controller *alloc_pci_controller(int seg)
-{
-	struct pci_controller *controller;
-
-	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
-	if (!controller)
-		return NULL;
-
-	controller->segment = seg;
-	return controller;
-}
-
 struct pci_root_info {
+	struct pci_controller controller;
 	struct acpi_device *bridge;
-	struct pci_controller *controller;
 	struct list_head resources;
-	struct resource *res;
-	resource_size_t *res_offset;
-	unsigned int res_num;
 	struct list_head io_resources;
-	char *name;
+	char name[16];
 };
 
 static unsigned int
@@ -168,11 +151,11 @@ new_space (u64 phys_base, int sparse)
 	return i;
 }
 
-static u64 add_io_space(struct pci_root_info *info,
-			struct acpi_resource_address64 *addr)
+static int add_io_space(struct device *dev, struct pci_root_info *info,
+			struct resource_entry *entry)
 {
 	struct iospace_resource *iospace;
-	struct resource *resource;
+	struct resource *resource, *res = entry->res;
 	char *name;
 	unsigned long base, min, max, base_port;
 	unsigned int sparse = 0, space_nr, len;
@@ -180,27 +163,24 @@ static u64 add_io_space(struct pci_root_info *info,
 	len = strlen(info->name) + 32;
 	iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL);
 	if (!iospace) {
-		dev_err(&info->bridge->dev,
-				"PCI: No memory for %s I/O port space\n",
-				info->name);
-		goto out;
+		dev_err(dev, "PCI: No memory for %s I/O port space\n",
+			info->name);
+		return -ENOMEM;
 	}
 
-	name = (char *)(iospace + 1);
-
-	min = addr->address.minimum;
-	max = min + addr->address.address_length - 1;
-	if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION)
+	if (res->flags & IORESOURCE_IO_SPARSE)
 		sparse = 1;
-
-	space_nr = new_space(addr->address.translation_offset, sparse);
+	space_nr = new_space(entry->offset, sparse);
 	if (space_nr == ~0)
 		goto free_resource;
 
+	name = (char *)(iospace + 1);
+	min = res->start - entry->offset;
+	max = res->end - entry->offset;
 	base = __pa(io_space[space_nr].mmio_base);
 	base_port = IO_SPACE_BASE(space_nr);
 	snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name,
-		base_port + min, base_port + max);
+		 base_port + min, base_port + max);
 
 	/*
 	 * The SDM guarantees the legacy 0-64K space is sparse, but if the
@@ -216,153 +196,195 @@ static u64 add_io_space(struct pci_root_info *info,
 	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
 	resource->end   = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
 	if (insert_resource(&iomem_resource, resource)) {
-		dev_err(&info->bridge->dev,
-				"can't allocate host bridge io space resource  %pR\n",
-				resource);
+		dev_err(dev,
+			"can't allocate host bridge io space resource  %pR\n",
+			resource);
 		goto free_resource;
 	}
 
+	entry->offset = base_port;
+	res->start = min + base_port;
+	res->end = max + base_port;
 	list_add_tail(&iospace->list, &info->io_resources);
-	return base_port;
+
+	return 0;
 
 free_resource:
 	kfree(iospace);
-out:
-	return ~0;
+	return -ENOSPC;
+}
+
+/*
+ * An IO port or MMIO resource assigned to a PCI host bridge may be
+ * consumed by the host bridge itself or available to its child
+ * bus/devices. The ACPI specification defines a bit (Producer/Consumer)
+ * to tell whether the resource is consumed by the host bridge itself,
+ * but firmware hasn't used that bit consistently, so we can't rely on it.
+ *
+ * On x86 and IA64 platforms, all IO port and MMIO resources are assumed
+ * to be available to child bus/devices except one special case:
+ *     IO port [0xCF8-0xCFF] is consumed by the host bridge itself
+ *     to access PCI configuration space.
+ *
+ * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF].
+ */
+static bool resource_is_pcicfg_ioport(struct resource *res)
+{
+	return (res->flags & IORESOURCE_IO) &&
+		res->start == 0xCF8 && res->end == 0xCFF;
 }
 
-static acpi_status resource_to_window(struct acpi_resource *resource,
-				      struct acpi_resource_address64 *addr)
+static int
+probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
+		    int busnum, int domain)
 {
-	acpi_status status;
+	int ret;
+	struct list_head *list = &info->resources;
+	struct resource_entry *entry, *tmp;
 
-	/*
-	 * We're only interested in _CRS descriptors that are
-	 *	- address space descriptors for memory or I/O space
-	 *	- non-zero size
-	 */
-	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)
-		return AE_OK;
-
-	return AE_ERROR;
-}
-
-static acpi_status count_window(struct acpi_resource *resource, void *data)
-{
-	unsigned int *windows = (unsigned int *) data;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
-
-	status = resource_to_window(resource, &addr);
-	if (ACPI_SUCCESS(status))
-		(*windows)++;
-
-	return AE_OK;
-}
-
-static acpi_status add_window(struct acpi_resource *res, void *data)
-{
-	struct pci_root_info *info = data;
-	struct resource *resource;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
-	unsigned long flags, offset = 0;
-	struct resource *root;
-
-	/* Return AE_OK for non-window resources to keep scanning for more */
-	status = resource_to_window(res, &addr);
-	if (!ACPI_SUCCESS(status))
-		return AE_OK;
-
-	if (addr.resource_type == ACPI_MEMORY_RANGE) {
-		flags = IORESOURCE_MEM;
-		root = &iomem_resource;
-		offset = addr.address.translation_offset;
-	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		flags = IORESOURCE_IO;
-		root = &ioport_resource;
-		offset = add_io_space(info, &addr);
-		if (offset == ~0)
-			return AE_OK;
-	} else
-		return AE_OK;
-
-	resource = &info->res[info->res_num];
-	resource->name = info->name;
-	resource->flags = flags;
-	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)) {
-		dev_err(&info->bridge->dev,
-			"can't allocate host bridge window %pR\n",
-			resource);
-	} else {
-		if (offset)
-			dev_info(&info->bridge->dev, "host bridge window %pR "
-				 "(PCI address [%#llx-%#llx])\n",
-				 resource,
-				 resource->start - offset,
-				 resource->end - offset);
-		else
-			dev_info(&info->bridge->dev,
-				 "host bridge window %pR\n", resource);
-	}
-	/* HP's firmware has a hack to work around a Windows bug.
-	 * Ignore these tiny memory ranges */
-	if (!((resource->flags & IORESOURCE_MEM) &&
-	      (resource->end - resource->start < 16)))
-		pci_add_resource_offset(&info->resources, resource,
-					info->res_offset[info->res_num]);
+	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_safe(entry, tmp, list) {
+			if ((entry->res->flags & IORESOURCE_DISABLED) ||
+			    resource_is_pcicfg_ioport(entry->res))
+				resource_list_destroy_entry(entry);
+			else
+				entry->res->name = info->name;
+		}
 
-	info->res_num++;
-	return AE_OK;
+	return ret;
 }
 
-static void free_pci_root_info_res(struct pci_root_info *info)
-{
-	struct iospace_resource *iospace, *tmp;
+static void validate_resources(struct device *dev, struct list_head *resources,
+			       unsigned long type)
+{
+	LIST_HEAD(list);
+	struct resource *res1, *res2, *root = NULL;
+	struct resource_entry *tmp, *entry, *entry2;
+
+	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
+	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
+
+	list_splice_init(resources, &list);
+	resource_list_for_each_entry_safe(entry, tmp, &list) {
+		bool free = false;
+		resource_size_t end;
+
+		res1 = entry->res;
+		if (!(res1->flags & type))
+			goto next;
+
+		/* Exclude non-addressable range or non-addressable portion */
+		end = min(res1->end, root->end);
+		if (end <= res1->start) {
+			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
+				 res1);
+			free = true;
+			goto next;
+		} else if (res1->end != end) {
+			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				 res1, (unsigned long long)end + 1,
+				 (unsigned long long)res1->end);
+			res1->end = end;
+		}
 
-	list_for_each_entry_safe(iospace, tmp, &info->io_resources, list)
-		kfree(iospace);
+		resource_list_for_each_entry(entry2, resources) {
+			res2 = entry2->res;
+			if (!(res2->flags & type))
+				continue;
+
+			/*
+			 * I don't like throwing away windows because then
+			 * our resources no longer match the ACPI _CRS, but
+			 * the kernel resource tree doesn't allow overlaps.
+			 */
+			if (resource_overlaps(res1, res2)) {
+				res2->start = min(res1->start, res2->start);
+				res2->end = max(res1->end, res2->end);
+				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
+					 res2, res1);
+				free = true;
+				goto next;
+			}
+		}
 
-	kfree(info->name);
-	kfree(info->res);
-	info->res = NULL;
-	kfree(info->res_offset);
-	info->res_offset = NULL;
-	info->res_num = 0;
-	kfree(info->controller);
-	info->controller = NULL;
+next:
+		resource_list_del(entry);
+		if (free)
+			resource_list_free_entry(entry);
+		else
+			resource_list_add_tail(entry, resources);
+	}
+}
+
+static void add_resources(struct pci_root_info *info, struct device *dev)
+{
+	struct resource_entry *entry, *tmp;
+	struct resource *res, *conflict, *root = NULL;
+	struct list_head *list = &info->resources;
+
+	validate_resources(dev, list, IORESOURCE_MEM);
+	validate_resources(dev, list, IORESOURCE_IO);
+
+	resource_list_for_each_entry_safe(entry, tmp, list) {
+		res = entry->res;
+		if (res->flags & IORESOURCE_MEM) {
+			root = &iomem_resource;
+			/*
+			 * HP's firmware has a hack to work around a Windows
+			 * bug. Ignore these tiny memory ranges.
+			 */
+			if (resource_size(res) <= 16) {
+				resource_list_destroy_entry(entry);
+				continue;
+			}
+		} else if (res->flags & IORESOURCE_IO) {
+			root = &ioport_resource;
+			if (add_io_space(&info->bridge->dev, info, entry)) {
+				resource_list_destroy_entry(entry);
+				continue;
+			}
+		} else {
+			BUG_ON(res);
+		}
+
+		conflict = insert_resource_conflict(root, res);
+		if (conflict) {
+			dev_info(dev,
+				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
+				 res, conflict->name, conflict);
+			resource_list_destroy_entry(entry);
+		}
+	}
 }
 
 static void __release_pci_root_info(struct pci_root_info *info)
 {
-	int i;
 	struct resource *res;
-	struct iospace_resource *iospace;
+	struct iospace_resource *iospace, *tmp;
+	struct resource_entry *entry, *tentry;
 
-	list_for_each_entry(iospace, &info->io_resources, list)
+	list_for_each_entry_safe(iospace, tmp, &info->io_resources, list) {
 		release_resource(&iospace->res);
+		kfree(iospace);
+	}
 
-	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_safe(entry, tentry, &info->resources) {
+		res = entry->res;
+		if (res->parent &&
+		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+			release_resource(res);
+		resource_list_destroy_entry(entry);
 	}
 
-	free_pci_root_info_res(info);
 	kfree(info);
 }
 
@@ -373,99 +395,49 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
 	__release_pci_root_info(info);
 }
 
-static int
-probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
-		int busnum, int domain)
-{
-	char *name;
-
-	name = kmalloc(16, GFP_KERNEL);
-	if (!name)
-		return -ENOMEM;
-
-	sprintf(name, "PCI Bus %04x:%02x", domain, busnum);
-	info->bridge = device;
-	info->name = name;
-
-	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
-			&info->res_num);
-	if (info->res_num) {
-		info->res =
-			kzalloc_node(sizeof(*info->res) * info->res_num,
-				     GFP_KERNEL, info->controller->node);
-		if (!info->res) {
-			kfree(name);
-			return -ENOMEM;
-		}
-
-		info->res_offset =
-			kzalloc_node(sizeof(*info->res_offset) * info->res_num,
-					GFP_KERNEL, info->controller->node);
-		if (!info->res_offset) {
-			kfree(name);
-			kfree(info->res);
-			info->res = NULL;
-			return -ENOMEM;
-		}
-
-		info->res_num = 0;
-		acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-			add_window, info);
-	} else
-		kfree(name);
-
-	return 0;
-}
-
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
 	struct acpi_device *device = root->device;
 	int domain = root->segment;
 	int bus = root->secondary.start;
-	struct pci_controller *controller;
-	struct pci_root_info *info = NULL;
-	int busnum = root->secondary.start;
+	struct pci_root_info *info;
 	struct pci_bus *pbus;
 	int ret;
 
-	controller = alloc_pci_controller(domain);
-	if (!controller)
-		return NULL;
-
-	controller->companion = device;
-	controller->node = acpi_get_node(device->handle);
-
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info) {
 		dev_err(&device->dev,
-				"pci_bus %04x:%02x: ignored (out of memory)\n",
-				domain, busnum);
-		kfree(controller);
+			"pci_bus %04x:%02x: ignored (out of memory)\n",
+			domain, bus);
 		return NULL;
 	}
 
-	info->controller = controller;
-	INIT_LIST_HEAD(&info->io_resources);
+	info->controller.segment = domain;
+	info->controller.companion = device;
+	info->controller.node = acpi_get_node(device->handle);
+	info->bridge = device;
 	INIT_LIST_HEAD(&info->resources);
+	INIT_LIST_HEAD(&info->io_resources);
+	snprintf(info->name, sizeof(info->name),
+		 "PCI Bus %04x:%02x", domain, bus);
 
-	ret = probe_pci_root_info(info, device, busnum, domain);
-	if (ret) {
-		kfree(info->controller);
+	ret = probe_pci_root_info(info, device, bus, domain);
+	if (ret <= 0) {
 		kfree(info);
 		return NULL;
 	}
-	/* insert busn resource at first */
+	add_resources(info, &info->bridge->dev);
 	pci_add_resource(&info->resources, &root->secondary);
+
 	/*
 	 * See arch/x86/pci/acpi.c.
 	 * The desired pci bus might already be scanned in a quirk. We
 	 * should handle the case here, but it appears that IA64 hasn't
 	 * such quirk. So we just ignore the case now.
 	 */
-	pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
-				   &info->resources);
+	pbus = pci_create_root_bus(NULL, bus, &pci_root_ops,
+				   &info->controller, &info->resources);
 	if (!pbus) {
-		pci_free_resource_list(&info->resources);
 		__release_pci_root_info(info);
 		return NULL;
 	}
-- 
1.7.10.4


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

* [Patch v3 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
  2015-05-14  8:56 ` [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
  2015-05-14  8:56 ` [Patch v3 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  2015-05-22 13:46   ` Hanjun Guo
  2015-05-14  8:56 ` [Patch v3 4/7] x86/PCI: Rename struct pci_sysdata as struct pci_controller Jiang Liu
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Tony Luck, Fenghua Yu, Jiang Liu, Yinghai Lu
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel, linux-ia64

Use common struct resource_entry to replace private
struct iospace_resource.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/ia64/include/asm/pci.h |    5 -----
 arch/ia64/pci/pci.c         |   17 ++++++++---------
 2 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 52af5ed9f60b..5c10e0ec48d4 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -83,11 +83,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
 #define pci_legacy_read platform_pci_legacy_read
 #define pci_legacy_write platform_pci_legacy_write
 
-struct iospace_resource {
-	struct list_head list;
-	struct resource res;
-};
-
 struct pci_controller {
 	struct acpi_device *companion;
 	void *iommu;
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 23689d4c37ae..4af1b52c7a44 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -154,14 +154,14 @@ new_space (u64 phys_base, int sparse)
 static int add_io_space(struct device *dev, struct pci_root_info *info,
 			struct resource_entry *entry)
 {
-	struct iospace_resource *iospace;
+	struct resource_entry *iospace;
 	struct resource *resource, *res = entry->res;
 	char *name;
 	unsigned long base, min, max, base_port;
 	unsigned int sparse = 0, space_nr, len;
 
 	len = strlen(info->name) + 32;
-	iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL);
+	iospace = resource_list_create_entry(NULL, len);
 	if (!iospace) {
 		dev_err(dev, "PCI: No memory for %s I/O port space\n",
 			info->name);
@@ -190,7 +190,7 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 	if (space_nr == 0)
 		sparse = 1;
 
-	resource = &iospace->res;
+	resource = iospace->res;
 	resource->name  = name;
 	resource->flags = IORESOURCE_MEM;
 	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
@@ -205,12 +205,12 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 	entry->offset = base_port;
 	res->start = min + base_port;
 	res->end = max + base_port;
-	list_add_tail(&iospace->list, &info->io_resources);
+	resource_list_add_tail(iospace, &info->io_resources);
 
 	return 0;
 
 free_resource:
-	kfree(iospace);
+	resource_list_free_entry(iospace);
 	return -ENOSPC;
 }
 
@@ -369,12 +369,11 @@ static void add_resources(struct pci_root_info *info, struct device *dev)
 static void __release_pci_root_info(struct pci_root_info *info)
 {
 	struct resource *res;
-	struct iospace_resource *iospace, *tmp;
 	struct resource_entry *entry, *tentry;
 
-	list_for_each_entry_safe(iospace, tmp, &info->io_resources, list) {
-		release_resource(&iospace->res);
-		kfree(iospace);
+	resource_list_for_each_entry_safe(entry, tentry, &info->io_resources) {
+		release_resource(entry->res);
+		resource_list_destroy_entry(entry);
 	}
 
 	resource_list_for_each_entry_safe(entry, tentry, &info->resources) {
-- 
1.7.10.4


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

* [Patch v3 4/7] x86/PCI: Rename struct pci_sysdata as struct pci_controller
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (2 preceding siblings ...)
  2015-05-14  8:56 ` [Patch v3 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  2015-05-14  8:56 ` [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86,
	Jiang Liu
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	linux-arm-kernel

Rename struct pci_sysdata as struct pci_controller, so we could share
common code between IA64 and x86 later.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/pci.h    |   13 +++++++------
 arch/x86/include/asm/pci_64.h |    4 ++--
 arch/x86/pci/acpi.c           |    8 ++++----
 arch/x86/pci/common.c         |    2 +-
 4 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 4e370a5d8117..243dafd86f87 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -11,15 +11,15 @@
 
 #ifdef __KERNEL__
 
-struct pci_sysdata {
-	int		domain;		/* PCI domain */
-	int		node;		/* NUMA node */
+struct pci_controller {
 #ifdef CONFIG_ACPI
 	struct acpi_device *companion;	/* ACPI companion device */
 #endif
 #ifdef CONFIG_X86_64
 	void		*iommu;		/* IOMMU private data */
 #endif
+	int		segment;	/* PCI domain */
+	int		node;		/* NUMA node */
 };
 
 extern int pci_routeirq;
@@ -31,8 +31,9 @@ extern int noioapicreroute;
 #ifdef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
-	struct pci_sysdata *sd = bus->sysdata;
-	return sd->domain;
+	struct pci_controller *sd = bus->sysdata;
+
+	return sd->segment;
 }
 
 static inline int pci_proc_domain(struct pci_bus *bus)
@@ -127,7 +128,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
 /* Returns the node based on pci bus */
 static inline int __pcibus_to_node(const struct pci_bus *bus)
 {
-	const struct pci_sysdata *sd = bus->sysdata;
+	const struct pci_controller *sd = bus->sysdata;
 
 	return sd->node;
 }
diff --git a/arch/x86/include/asm/pci_64.h b/arch/x86/include/asm/pci_64.h
index fe15cfb21b9b..dcbb6b52d4fd 100644
--- a/arch/x86/include/asm/pci_64.h
+++ b/arch/x86/include/asm/pci_64.h
@@ -6,13 +6,13 @@
 #ifdef CONFIG_CALGARY_IOMMU
 static inline void *pci_iommu(struct pci_bus *bus)
 {
-	struct pci_sysdata *sd = bus->sysdata;
+	struct pci_controller *sd = bus->sysdata;
 	return sd->iommu;
 }
 
 static inline void set_pci_iommu(struct pci_bus *bus, void *val)
 {
-	struct pci_sysdata *sd = bus->sysdata;
+	struct pci_controller *sd = bus->sysdata;
 	sd->iommu = val;
 }
 #endif /* CONFIG_CALGARY_IOMMU */
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index d93963340c3c..b34a2b660de3 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -10,7 +10,7 @@
 struct pci_root_info {
 	struct acpi_device *bridge;
 	char name[16];
-	struct pci_sysdata sd;
+	struct pci_controller sd;
 #ifdef	CONFIG_PCI_MMCONFIG
 	bool mcfg_added;
 	u16 segment;
@@ -384,7 +384,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	LIST_HEAD(crs_res);
 	LIST_HEAD(resources);
 	struct pci_bus *bus;
-	struct pci_sysdata *sd;
+	struct pci_controller *sd;
 	int node;
 
 	if (pci_ignore_seg)
@@ -416,7 +416,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	}
 
 	sd = &info->sd;
-	sd->domain = domain;
+	sd->segment = domain;
 	sd->node = node;
 	sd->companion = device;
 
@@ -482,7 +482,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
-	struct pci_sysdata *sd = bridge->bus->sysdata;
+	struct pci_controller *sd = bridge->bus->sysdata;
 
 	ACPI_COMPANION_SET(&bridge->dev, sd->companion);
 	return 0;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 8fd6f44aee83..10f37d0ce5d8 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -475,7 +475,7 @@ void __init dmi_check_pciprobe(void)
 void pcibios_scan_root(int busnum)
 {
 	struct pci_bus *bus;
-	struct pci_sysdata *sd;
+	struct pci_controller *sd;
 	LIST_HEAD(resources);
 
 	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
-- 
1.7.10.4


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

* [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (3 preceding siblings ...)
  2015-05-14  8:56 ` [Patch v3 4/7] x86/PCI: Rename struct pci_sysdata as struct pci_controller Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  2015-05-18 13:08   ` Hanjun Guo
  2015-05-22 13:49   ` Hanjun Guo
  2015-05-14  8:56 ` [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
  2015-05-14  8:56 ` [Patch v3 7/7] ia64/PCI/ACPI: " Jiang Liu
  6 siblings, 2 replies; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Len Brown
  Cc: Jiang Liu, Lv Zheng, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel

Introduce common interface acpi_pci_root_create() and related data
structures to create PCI root bus for ACPI PCI host bridges. It will
be used to kill duplicated arch specific code for IA64 and x86. It may
also help ARM64 in future.

Tested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/pci_root.c  |  200 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci-acpi.h |   23 ++++++
 2 files changed, 223 insertions(+)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 1b5569c092c6..22d0cb799ef1 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -656,6 +656,206 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 	kfree(root);
 }
 
+static void acpi_pci_root_validate_resources(struct device *dev,
+					     struct list_head *resources,
+					     unsigned long type)
+{
+	LIST_HEAD(list);
+	struct resource *res1, *res2, *root = NULL;
+	struct resource_entry *tmp, *entry, *entry2;
+
+	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
+	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
+
+	list_splice_init(resources, &list);
+	resource_list_for_each_entry_safe(entry, tmp, &list) {
+		bool free = false;
+		resource_size_t end;
+
+		res1 = entry->res;
+		if (!(res1->flags & type))
+			goto next;
+
+		/* Exclude non-addressable range or non-addressable portion */
+		end = min(res1->end, root->end);
+		if (end <= res1->start) {
+			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
+				 res1);
+			free = true;
+			goto next;
+		} else if (res1->end != end) {
+			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				 res1, (unsigned long long)end + 1,
+				 (unsigned long long)res1->end);
+			res1->end = end;
+		}
+
+		resource_list_for_each_entry(entry2, resources) {
+			res2 = entry2->res;
+			if (!(res2->flags & type))
+				continue;
+
+			/*
+			 * I don't like throwing away windows because then
+			 * our resources no longer match the ACPI _CRS, but
+			 * the kernel resource tree doesn't allow overlaps.
+			 */
+			if (resource_overlaps(res1, res2)) {
+				res2->start = min(res1->start, res2->start);
+				res2->end = max(res1->end, res2->end);
+				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
+					 res2, res1);
+				free = true;
+				goto next;
+			}
+		}
+
+next:
+		resource_list_del(entry);
+		if (free)
+			resource_list_free_entry(entry);
+		else
+			resource_list_add_tail(entry, resources);
+	}
+}
+
+static int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
+{
+	int ret;
+	struct list_head *list = &info->resources;
+	struct acpi_device *device = info->bridge;
+	struct resource_entry *entry, *tmp;
+	unsigned long flags;
+
+	flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
+	ret = acpi_dev_get_resources(device, list,
+				     acpi_dev_filter_resource_type_cb,
+				     (void *)flags);
+	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_safe(entry, tmp, list) {
+			if (entry->res->flags & IORESOURCE_DISABLED)
+				resource_list_destroy_entry(entry);
+			else
+				entry->res->name = info->name;
+		}
+		acpi_pci_root_validate_resources(&device->dev, list,
+						 IORESOURCE_MEM);
+		acpi_pci_root_validate_resources(&device->dev, list,
+						 IORESOURCE_IO);
+	}
+
+	return ret;
+}
+
+static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
+{
+	struct resource_entry *entry, *tmp;
+	struct resource *res, *conflict, *root = NULL;
+
+	resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
+		res = entry->res;
+		if (res->flags & IORESOURCE_MEM)
+			root = &iomem_resource;
+		else if (res->flags & IORESOURCE_IO)
+			root = &ioport_resource;
+		else
+			continue;
+
+		conflict = insert_resource_conflict(root, res);
+		if (conflict) {
+			dev_info(&info->bridge->dev,
+				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
+				 res, conflict->name, conflict);
+			resource_list_destroy_entry(entry);
+		}
+	}
+}
+
+static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
+{
+	struct resource *res;
+	struct resource_entry *entry, *tmp;
+
+	if (!info)
+		return;
+
+	resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
+		res = entry->res;
+		if (res->parent &&
+		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+			release_resource(res);
+		resource_list_destroy_entry(entry);
+	}
+
+	info->ops->release_info(info);
+}
+
+static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
+{
+	struct resource *res;
+	struct resource_entry *entry;
+
+	resource_list_for_each_entry(entry, &bridge->windows) {
+		res = entry->res;
+		if (res->parent &&
+		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+			release_resource(res);
+	}
+	__acpi_pci_root_release_info(bridge->release_data);
+}
+
+struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+				     struct acpi_pci_root_ops *ops,
+				     struct acpi_pci_root_info *info)
+{
+	int ret, busnum = root->secondary.start;
+	struct acpi_device *device = root->device;
+	struct pci_bus *bus;
+
+	info->controller.segment = root->segment;
+	info->controller.node = acpi_get_node(device->handle);
+	info->controller.companion = device;
+	info->root = root;
+	info->bridge = device;
+	info->ops = ops;
+	INIT_LIST_HEAD(&info->resources);
+	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
+		 info->controller.segment, busnum);
+
+	if (ops->init_info && ops->init_info(info))
+		goto out_release_info;
+	ret = acpi_pci_probe_root_resources(info);
+	if (ops->prepare_resources)
+		ret = ops->prepare_resources(info, ret);
+	if (ret < 0)
+		goto out_release_info;
+	else if (ret > 0)
+		pci_acpi_root_add_resources(info);
+	pci_add_resource(&info->resources, &root->secondary);
+
+	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
+				  &info->controller, &info->resources);
+	if (bus) {
+		pci_scan_child_bus(bus);
+		pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
+					    acpi_pci_root_release_info, info);
+		if (info->controller.node != NUMA_NO_NODE)
+			dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n",
+				   info->controller.node);
+		return bus;
+	}
+
+out_release_info:
+	__acpi_pci_root_release_info(info);
+	return NULL;
+}
+
 void __init acpi_pci_root_init(void)
 {
 	acpi_hest_init();
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index a965efa52152..685ccc4c3170 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -52,6 +52,29 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 	return ACPI_HANDLE(dev);
 }
 
+struct acpi_pci_root;
+struct acpi_pci_root_ops;
+
+struct acpi_pci_root_info {
+	struct pci_controller		controller;
+	struct acpi_pci_root		*root;
+	struct acpi_device		*bridge;
+	struct acpi_pci_root_ops	*ops;
+	struct list_head		resources;
+	char				name[16];
+};
+
+struct acpi_pci_root_ops {
+	struct pci_ops *pci_ops;
+	int (*init_info)(struct acpi_pci_root_info *info);
+	void (*release_info)(struct acpi_pci_root_info *info);
+	int (*prepare_resources)(struct acpi_pci_root_info *info, int status);
+};
+
+extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+					    struct acpi_pci_root_ops *ops,
+					    struct acpi_pci_root_info *info);
+
 void acpi_pci_add_bus(struct pci_bus *bus);
 void acpi_pci_remove_bus(struct pci_bus *bus);
 
-- 
1.7.10.4


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

* [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (4 preceding siblings ...)
  2015-05-14  8:56 ` [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  2015-05-22 13:55   ` Hanjun Guo
  2015-05-14  8:56 ` [Patch v3 7/7] ia64/PCI/ACPI: " Jiang Liu
  6 siblings, 1 reply; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86
  Cc: Jiang Liu, Lv Zheng, lenb @ kernel . org, LKML, linux-pci,
	linux-acpi, linux-arm-kernel

Use common interface to simplify ACPI PCI host bridge implementation.

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

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index b34a2b660de3..89bd79be418c 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -4,16 +4,14 @@
 #include <linux/irq.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/pci-acpi.h>
 #include <asm/numa.h>
 #include <asm/pci_x86.h>
 
 struct pci_root_info {
-	struct acpi_device *bridge;
-	char name[16];
-	struct pci_controller sd;
+	struct acpi_pci_root_info common;
 #ifdef	CONFIG_PCI_MMCONFIG
 	bool mcfg_added;
-	u16 segment;
 	u8 start_bus;
 	u8 end_bus;
 #endif
@@ -165,14 +163,17 @@ static int check_segment(u16 seg, struct device *dev, char *estr)
 	return 0;
 }
 
-static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
-			  u8 end, phys_addr_t addr)
+static int setup_mcfg_map(struct acpi_pci_root_info *ci)
 {
 	int result;
-	struct device *dev = &info->bridge->dev;
+	struct pci_root_info *info;
+	struct acpi_pci_root *root = ci->root;
+	struct device *dev = &ci->bridge->dev;
+	int seg = ci->controller.segment;
 
-	info->start_bus = start;
-	info->end_bus = end;
+	info = container_of(ci, struct pci_root_info, common);
+	info->start_bus = (u8)root->secondary.start;
+	info->end_bus = (u8)root->secondary.end;
 	info->mcfg_added = false;
 
 	/* return success if MMCFG is not in use */
@@ -182,7 +183,8 @@ static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
 	if (!(pci_probe & PCI_PROBE_MMCONF))
 		return check_segment(seg, dev, "MMCONFIG is disabled,");
 
-	result = pci_mmconfig_insert(dev, seg, start, end, addr);
+	result = pci_mmconfig_insert(dev, seg, info->start_bus, info->end_bus,
+				     root->mcfg_addr);
 	if (result == 0) {
 		/* enable MMCFG if it hasn't been enabled yet */
 		if (raw_pci_ext_ops == NULL)
@@ -195,134 +197,59 @@ static int setup_mcfg_map(struct pci_root_info *info, u16 seg, u8 start,
 	return 0;
 }
 
-static void teardown_mcfg_map(struct pci_root_info *info)
+static void teardown_mcfg_map(struct acpi_pci_root_info *ci)
 {
+	struct pci_root_info *info;
+
+	info = container_of(ci, struct pci_root_info, common);
 	if (info->mcfg_added) {
-		pci_mmconfig_delete(info->segment, info->start_bus,
-				    info->end_bus);
+		pci_mmconfig_delete(ci->controller.segment,
+				    info->start_bus, info->end_bus);
 		info->mcfg_added = false;
 	}
 }
 #else
-static int setup_mcfg_map(struct pci_root_info *info,
-				    u16 seg, u8 start, u8 end,
-				    phys_addr_t addr)
+static int setup_mcfg_map(struct acpi_pci_root_info *ci)
 {
 	return 0;
 }
-static void teardown_mcfg_map(struct pci_root_info *info)
+
+static void teardown_mcfg_map(struct acpi_pci_root_info *ci)
 {
 }
 #endif
 
-static void validate_resources(struct device *dev, struct list_head *crs_res,
-			       unsigned long type)
+static int pci_acpi_root_get_node(struct acpi_pci_root *root)
 {
-	LIST_HEAD(list);
-	struct resource *res1, *res2, *root = NULL;
-	struct resource_entry *tmp, *entry, *entry2;
-
-	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
-	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
-
-	list_splice_init(crs_res, &list);
-	resource_list_for_each_entry_safe(entry, tmp, &list) {
-		bool free = false;
-		resource_size_t end;
-
-		res1 = entry->res;
-		if (!(res1->flags & type))
-			goto next;
-
-		/* Exclude non-addressable range or non-addressable portion */
-		end = min(res1->end, root->end);
-		if (end <= res1->start) {
-			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
-				 res1);
-			free = true;
-			goto next;
-		} else if (res1->end != end) {
-			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
-				 res1, (unsigned long long)end + 1,
-				 (unsigned long long)res1->end);
-			res1->end = end;
-		}
-
-		resource_list_for_each_entry(entry2, crs_res) {
-			res2 = entry2->res;
-			if (!(res2->flags & type))
-				continue;
-
-			/*
-			 * I don't like throwing away windows because then
-			 * our resources no longer match the ACPI _CRS, but
-			 * the kernel resource tree doesn't allow overlaps.
-			 */
-			if (resource_overlaps(res1, res2)) {
-				res2->start = min(res1->start, res2->start);
-				res2->end = max(res1->end, res2->end);
-				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
-					 res2, res1);
-				free = true;
-				goto next;
-			}
-		}
-
-next:
-		resource_list_del(entry);
-		if (free)
-			resource_list_free_entry(entry);
-		else
-			resource_list_add_tail(entry, crs_res);
+	int busnum = root->secondary.start;
+	struct acpi_device *device = root->device;
+	int node = acpi_get_node(device->handle);
+
+	if (node == NUMA_NO_NODE) {
+		node = x86_pci_root_bus_node(busnum);
+		if (node != 0 && node != NUMA_NO_NODE)
+			dev_info(&device->dev, FW_BUG "no _PXM; falling back to node %d from hardware (may be inconsistent with ACPI node numbers)\n",
+				node);
 	}
+	if (node != NUMA_NO_NODE && !node_online(node))
+		node = NUMA_NO_NODE;
+
+	return node;
 }
 
-static void add_resources(struct pci_root_info *info,
-			  struct list_head *resources,
-			  struct list_head *crs_res)
+static int pci_acpi_root_init_info(struct acpi_pci_root_info *ci)
 {
-	struct resource_entry *entry, *tmp;
-	struct resource *res, *conflict, *root = NULL;
-
-	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
-			BUG_ON(res);
-
-		conflict = insert_resource_conflict(root, res);
-		if (conflict) {
-			dev_info(&info->bridge->dev,
-				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
-				 res, conflict->name, conflict);
-			resource_list_destroy_entry(entry);
-		}
-	}
+	ci->controller.node = pci_acpi_root_get_node(ci->root);
+	if (pci_ignore_seg)
+		ci->controller.segment = 0;
 
-	list_splice_tail(crs_res, resources);
+	return setup_mcfg_map(ci);
 }
 
-static void release_pci_root_info(struct pci_host_bridge *bridge)
+static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
 {
-	struct resource *res;
-	struct resource_entry *entry;
-	struct pci_root_info *info = bridge->release_data;
-
-	resource_list_for_each_entry(entry, &bridge->windows) {
-		res = entry->res;
-		if (res->parent &&
-		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
-			release_resource(res);
-	}
-
-	teardown_mcfg_map(info);
-	kfree(info);
+	teardown_mcfg_map(ci);
+	kfree(ci);
 }
 
 /*
@@ -345,47 +272,43 @@ static bool resource_is_pcicfg_ioport(struct resource *res)
 		res->start == 0xCF8 && res->end == 0xCFF;
 }
 
-static void probe_pci_root_info(struct pci_root_info *info,
-				struct acpi_device *device,
-				int busnum, int domain,
-				struct list_head *list)
+static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci,
+					   int status)
 {
-	int ret;
+	struct acpi_device *device = ci->bridge;
+	int busnum = ci->root->secondary.start;
 	struct resource_entry *entry, *tmp;
 
-	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
-	info->bridge = device;
-	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_safe(entry, tmp, list) {
-			if ((entry->res->flags & IORESOURCE_DISABLED) ||
-			    resource_is_pcicfg_ioport(entry->res))
+	if (pci_use_crs) {
+		resource_list_for_each_entry_safe(entry, tmp, &ci->resources)
+			if (resource_is_pcicfg_ioport(entry->res))
 				resource_list_destroy_entry(entry);
-			else
-				entry->res->name = info->name;
-		}
+		return status;
+	}
+
+	resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
+		dev_printk(KERN_DEBUG, &device->dev,
+			   "host bridge window %pR (ignored)\n", entry->res);
+		resource_list_destroy_entry(entry);
+	}
+	x86_pci_root_bus_resources(busnum, &ci->resources);
+
+	return 0;
 }
 
+static struct acpi_pci_root_ops acpi_pci_root_ops = {
+	.pci_ops = &pci_root_ops,
+	.init_info = pci_acpi_root_init_info,
+	.release_info = pci_acpi_root_release_info,
+	.prepare_resources = pci_acpi_root_prepare_resources,
+};
+
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
-	struct acpi_device *device = root->device;
-	struct pci_root_info *info;
 	int domain = root->segment;
 	int busnum = root->secondary.start;
-	struct resource_entry *res_entry;
-	LIST_HEAD(crs_res);
-	LIST_HEAD(resources);
+	int node = pci_acpi_root_get_node(root);
 	struct pci_bus *bus;
-	struct pci_controller *sd;
-	int node;
 
 	if (pci_ignore_seg)
 		domain = 0;
@@ -397,72 +320,30 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 		return NULL;
 	}
 
-	node = acpi_get_node(device->handle);
-	if (node == NUMA_NO_NODE) {
-		node = x86_pci_root_bus_node(busnum);
-		if (node != 0 && node != NUMA_NO_NODE)
-			dev_info(&device->dev, FW_BUG "no _PXM; falling back to node %d from hardware (may be inconsistent with ACPI node numbers)\n",
-				node);
-	}
-
-	if (node != NUMA_NO_NODE && !node_online(node))
-		node = NUMA_NO_NODE;
-
-	info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
-	if (!info) {
-		printk(KERN_WARNING "pci_bus %04x:%02x: "
-		       "ignored (out of memory)\n", domain, busnum);
-		return NULL;
-	}
-
-	sd = &info->sd;
-	sd->segment = domain;
-	sd->node = node;
-	sd->companion = device;
-
 	bus = pci_find_bus(domain, busnum);
 	if (bus) {
 		/*
 		 * If the desired bus has been scanned already, replace
 		 * its bus->sysdata.
 		 */
-		memcpy(bus->sysdata, sd, sizeof(*sd));
-		kfree(info);
+		struct pci_controller sd = {
+			.segment = domain,
+			.node = node,
+			.companion = root->device
+		};
+
+		memcpy(bus->sysdata, &sd, sizeof(sd));
 	} else {
-		/* insert busn res at first */
-		pci_add_resource(&resources,  &root->secondary);
+		struct pci_root_info *info;
 
-		/*
-		 * _CRS with no apertures is normal, so only fall back to
-		 * defaults or native bridge info if we're ignoring _CRS.
-		 */
-		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);
-		}
-
-		if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
-				    (u8)root->secondary.end, root->mcfg_addr))
-			bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
-						  sd, &resources);
-
-		if (bus) {
-			pci_scan_child_bus(bus);
-			pci_set_host_bridge_release(
-				to_pci_host_bridge(bus->bridge),
-				release_pci_root_info, info);
-		} else {
-			resource_list_free(&resources);
-			teardown_mcfg_map(info);
-			kfree(info);
-		}
+		info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
+		if (!info)
+			dev_err(&root->device->dev,
+				"pci_bus %04x:%02x: ignored (out of memory)\n",
+				domain, busnum);
+		else
+			bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
+						   &info->common);
 	}
 
 	/* After the PCI-E bus has been walked and all devices discovered,
@@ -474,9 +355,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 			pcie_bus_configure_settings(child);
 	}
 
-	if (bus && node != NUMA_NO_NODE)
-		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
-
 	return bus;
 }
 
-- 
1.7.10.4


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

* [Patch v3 7/7] ia64/PCI/ACPI: Use common interface to support PCI host bridge
  2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (5 preceding siblings ...)
  2015-05-14  8:56 ` [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
@ 2015-05-14  8:56 ` Jiang Liu
  6 siblings, 0 replies; 19+ messages in thread
From: Jiang Liu @ 2015-05-14  8:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier, Hanjun Guo,
	Yijing Wang, Tony Luck, Fenghua Yu, Jiang Liu, Yinghai Lu
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel, linux-ia64

Use common interface to simplify PCI host bridge implementation.

Tested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/ia64/pci/pci.c |  235 ++++++++++-----------------------------------------
 1 file changed, 45 insertions(+), 190 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 4af1b52c7a44..ccff9c535239 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -116,15 +116,11 @@ struct pci_ops pci_root_ops = {
 };
 
 struct pci_root_info {
-	struct pci_controller controller;
-	struct acpi_device *bridge;
-	struct list_head resources;
+	struct acpi_pci_root_info common;
 	struct list_head io_resources;
-	char name[16];
 };
 
-static unsigned int
-new_space (u64 phys_base, int sparse)
+static unsigned int new_space(u64 phys_base, int sparse)
 {
 	u64 mmio_base;
 	int i;
@@ -160,11 +156,11 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 	unsigned long base, min, max, base_port;
 	unsigned int sparse = 0, space_nr, len;
 
-	len = strlen(info->name) + 32;
+	len = strlen(info->common.name) + 32;
 	iospace = resource_list_create_entry(NULL, len);
 	if (!iospace) {
 		dev_err(dev, "PCI: No memory for %s I/O port space\n",
-			info->name);
+			info->common.name);
 		return -ENOMEM;
 	}
 
@@ -179,7 +175,7 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 	max = res->end - entry->offset;
 	base = __pa(io_space[space_nr].mmio_base);
 	base_port = IO_SPACE_BASE(space_nr);
-	snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name,
+	snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->common.name,
 		 base_port + min, base_port + max);
 
 	/*
@@ -234,217 +230,76 @@ static bool resource_is_pcicfg_ioport(struct resource *res)
 		res->start == 0xCF8 && res->end == 0xCFF;
 }
 
-static int
-probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
-		    int busnum, int domain)
+static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci,
+					   int status)
 {
-	int ret;
-	struct list_head *list = &info->resources;
+	struct device *dev = &ci->bridge->dev;
+	struct pci_root_info *info;
+	struct resource *res;
 	struct resource_entry *entry, *tmp;
 
-	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_safe(entry, tmp, list) {
-			if ((entry->res->flags & IORESOURCE_DISABLED) ||
-			    resource_is_pcicfg_ioport(entry->res))
-				resource_list_destroy_entry(entry);
-			else
-				entry->res->name = info->name;
-		}
-
-	return ret;
-}
-
-static void validate_resources(struct device *dev, struct list_head *resources,
-			       unsigned long type)
-{
-	LIST_HEAD(list);
-	struct resource *res1, *res2, *root = NULL;
-	struct resource_entry *tmp, *entry, *entry2;
-
-	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
-	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
-
-	list_splice_init(resources, &list);
-	resource_list_for_each_entry_safe(entry, tmp, &list) {
-		bool free = false;
-		resource_size_t end;
-
-		res1 = entry->res;
-		if (!(res1->flags & type))
-			goto next;
-
-		/* Exclude non-addressable range or non-addressable portion */
-		end = min(res1->end, root->end);
-		if (end <= res1->start) {
-			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
-				 res1);
-			free = true;
-			goto next;
-		} else if (res1->end != end) {
-			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
-				 res1, (unsigned long long)end + 1,
-				 (unsigned long long)res1->end);
-			res1->end = end;
-		}
-
-		resource_list_for_each_entry(entry2, resources) {
-			res2 = entry2->res;
-			if (!(res2->flags & type))
-				continue;
-
-			/*
-			 * I don't like throwing away windows because then
-			 * our resources no longer match the ACPI _CRS, but
-			 * the kernel resource tree doesn't allow overlaps.
-			 */
-			if (resource_overlaps(res1, res2)) {
-				res2->start = min(res1->start, res2->start);
-				res2->end = max(res1->end, res2->end);
-				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
-					 res2, res1);
-				free = true;
-				goto next;
+	if (status > 0) {
+		info = container_of(ci, struct pci_root_info, common);
+		resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
+			res = entry->res;
+			if (res->flags & IORESOURCE_MEM) {
+				/*
+				 * HP's firmware has a hack to work around a
+				 * Windows bug. Ignore these tiny memory ranges.
+				 */
+				if (resource_size(res) <= 16) {
+					resource_list_del(entry);
+					insert_resource(&iomem_resource,
+							entry->res);
+					resource_list_add_tail(entry,
+							&info->io_resources);
+				}
+			} else if (res->flags & IORESOURCE_IO) {
+				if (resource_is_pcicfg_ioport(entry->res))
+					resource_list_destroy_entry(entry);
+				else if (add_io_space(dev, info, entry))
+					resource_list_destroy_entry(entry);
 			}
 		}
-
-next:
-		resource_list_del(entry);
-		if (free)
-			resource_list_free_entry(entry);
-		else
-			resource_list_add_tail(entry, resources);
 	}
-}
 
-static void add_resources(struct pci_root_info *info, struct device *dev)
-{
-	struct resource_entry *entry, *tmp;
-	struct resource *res, *conflict, *root = NULL;
-	struct list_head *list = &info->resources;
-
-	validate_resources(dev, list, IORESOURCE_MEM);
-	validate_resources(dev, list, IORESOURCE_IO);
-
-	resource_list_for_each_entry_safe(entry, tmp, list) {
-		res = entry->res;
-		if (res->flags & IORESOURCE_MEM) {
-			root = &iomem_resource;
-			/*
-			 * HP's firmware has a hack to work around a Windows
-			 * bug. Ignore these tiny memory ranges.
-			 */
-			if (resource_size(res) <= 16) {
-				resource_list_destroy_entry(entry);
-				continue;
-			}
-		} else if (res->flags & IORESOURCE_IO) {
-			root = &ioport_resource;
-			if (add_io_space(&info->bridge->dev, info, entry)) {
-				resource_list_destroy_entry(entry);
-				continue;
-			}
-		} else {
-			BUG_ON(res);
-		}
-
-		conflict = insert_resource_conflict(root, res);
-		if (conflict) {
-			dev_info(dev,
-				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
-				 res, conflict->name, conflict);
-			resource_list_destroy_entry(entry);
-		}
-	}
+	return status;
 }
 
-static void __release_pci_root_info(struct pci_root_info *info)
+static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
 {
-	struct resource *res;
-	struct resource_entry *entry, *tentry;
+	struct pci_root_info *info;
+	struct resource_entry *entry, *tmp;
 
-	resource_list_for_each_entry_safe(entry, tentry, &info->io_resources) {
+	info = container_of(ci, struct pci_root_info, common);
+	resource_list_for_each_entry_safe(entry, tmp, &info->io_resources) {
 		release_resource(entry->res);
 		resource_list_destroy_entry(entry);
 	}
-
-	resource_list_for_each_entry_safe(entry, tentry, &info->resources) {
-		res = entry->res;
-		if (res->parent &&
-		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
-			release_resource(res);
-		resource_list_destroy_entry(entry);
-	}
-
 	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 struct acpi_pci_root_ops pci_acpi_root_ops = {
+	.pci_ops = &pci_root_ops,
+	.release_info = pci_acpi_root_release_info,
+	.prepare_resources = pci_acpi_root_prepare_resources,
+};
 
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
-	struct acpi_device *device = root->device;
-	int domain = root->segment;
-	int bus = root->secondary.start;
 	struct pci_root_info *info;
-	struct pci_bus *pbus;
-	int ret;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info) {
-		dev_err(&device->dev,
+		dev_err(&root->device->dev,
 			"pci_bus %04x:%02x: ignored (out of memory)\n",
-			domain, bus);
+			root->segment, (int)root->secondary.start);
 		return NULL;
 	}
 
-	info->controller.segment = domain;
-	info->controller.companion = device;
-	info->controller.node = acpi_get_node(device->handle);
-	info->bridge = device;
-	INIT_LIST_HEAD(&info->resources);
 	INIT_LIST_HEAD(&info->io_resources);
-	snprintf(info->name, sizeof(info->name),
-		 "PCI Bus %04x:%02x", domain, bus);
-
-	ret = probe_pci_root_info(info, device, bus, domain);
-	if (ret <= 0) {
-		kfree(info);
-		return NULL;
-	}
-	add_resources(info, &info->bridge->dev);
-	pci_add_resource(&info->resources, &root->secondary);
-
-	/*
-	 * See arch/x86/pci/acpi.c.
-	 * The desired pci bus might already be scanned in a quirk. We
-	 * should handle the case here, but it appears that IA64 hasn't
-	 * such quirk. So we just ignore the case now.
-	 */
-	pbus = pci_create_root_bus(NULL, bus, &pci_root_ops,
-				   &info->controller, &info->resources);
-	if (!pbus) {
-		__release_pci_root_info(info);
-		return NULL;
-	}
 
-	pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge),
-			release_pci_root_info, info);
-	pci_scan_child_bus(pbus);
-	return pbus;
+	return acpi_pci_root_create(root, &pci_acpi_root_ops, &info->common);
 }
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-- 
1.7.10.4


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

* Re: [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  2015-05-14  8:56 ` [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
@ 2015-05-18 13:08   ` Hanjun Guo
  2015-05-20  3:16     ` Jiang Liu
  2015-05-22 13:49   ` Hanjun Guo
  1 sibling, 1 reply; 19+ messages in thread
From: Hanjun Guo @ 2015-05-18 13:08 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Len Brown
  Cc: Lv Zheng, LKML, linux-pci, linux-acpi, x86 @ kernel . org,
	linux-arm-kernel

Hi Jiang,

On 2015年05月14日 16:56, Jiang Liu wrote:
> Introduce common interface acpi_pci_root_create() and related data
> structures to create PCI root bus for ACPI PCI host bridges. It will
> be used to kill duplicated arch specific code for IA64 and x86. It may
> also help ARM64 in future.

As I commented in previous version, this patch will introduce
compile error on ACPI enabled ARM64 kernel because struct
pci_controller is not defined for ARM64, so how about adding
the following patch before this patch, or squash to this one,
does it make sense?

 From 11d0e98154e681e75936698208398cb4dcd73632 Mon Sep 17 00:00:00 2001
From: Hanjun Guo <hanjun.guo@linaro.org>
Date: Mon, 18 May 2015 19:41:56 +0800
Subject: [PATCH] ARM64 / PCI: introduce struct pci_controller for ACPI

ARM64 ACPI based PCI host bridge init needs a arch dependent
struct pci_controller to accommodate common PCI host bridge
code which is introduced later, or it will lead to compile
errors on ARM64.

Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
CC: Liviu Dudau <Liviu.Dudau@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
  arch/arm64/include/asm/pci.h | 10 ++++++++++
  1 file changed, 10 insertions(+)

diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
index b008a72..7088495 100644
--- a/arch/arm64/include/asm/pci.h
+++ b/arch/arm64/include/asm/pci.h
@@ -10,6 +10,16 @@
  #include <asm-generic/pci-bridge.h>
  #include <asm-generic/pci-dma-compat.h>

+struct acpi_device;
+
+struct pci_controller {
+#ifdef CONFIG_ACPI
+       struct acpi_device *companion;  /* ACPI companion device */
+#endif
+       int             segment;        /* PCI domain */
+       int             node;           /* NUMA node */
+};
+
  #define PCIBIOS_MIN_IO         0x1000
  #define PCIBIOS_MIN_MEM                0


Thanks
Hanjun

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

* Re: [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  2015-05-18 13:08   ` Hanjun Guo
@ 2015-05-20  3:16     ` Jiang Liu
  2015-05-20  3:33       ` Hanjun Guo
  0 siblings, 1 reply; 19+ messages in thread
From: Jiang Liu @ 2015-05-20  3:16 UTC (permalink / raw)
  To: Hanjun Guo, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Len Brown
  Cc: Lv Zheng, LKML, linux-pci, linux-acpi, x86 @ kernel . org,
	linux-arm-kernel

On 2015/5/18 21:08, Hanjun Guo wrote:
> Hi Jiang,
> 
> On 2015年05月14日 16:56, Jiang Liu wrote:
>> Introduce common interface acpi_pci_root_create() and related data
>> structures to create PCI root bus for ACPI PCI host bridges. It will
>> be used to kill duplicated arch specific code for IA64 and x86. It may
>> also help ARM64 in future.
> 
> As I commented in previous version, this patch will introduce
> compile error on ACPI enabled ARM64 kernel because struct
> pci_controller is not defined for ARM64, so how about adding
> the following patch before this patch, or squash to this one,
> does it make sense?
Hi Hanjun,
	Thanks for fixing this building issue for ARM64. The patch
is really what I want:). Will merge it into next version. With this
patch applied, are there any other issues from ARM64 side?
Thanks!
Gerry

> 
> From 11d0e98154e681e75936698208398cb4dcd73632 Mon Sep 17 00:00:00 2001
> From: Hanjun Guo <hanjun.guo@linaro.org>
> Date: Mon, 18 May 2015 19:41:56 +0800
> Subject: [PATCH] ARM64 / PCI: introduce struct pci_controller for ACPI
> 
> ARM64 ACPI based PCI host bridge init needs a arch dependent
> struct pci_controller to accommodate common PCI host bridge
> code which is introduced later, or it will lead to compile
> errors on ARM64.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> CC: Liviu Dudau <Liviu.Dudau@arm.com>
> CC: Will Deacon <will.deacon@arm.com>
> CC: Catalin Marinas <catalin.marinas@arm.com>
> CC: Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
> CC: Arnd Bergmann <arnd@arndb.de>
> ---
>  arch/arm64/include/asm/pci.h | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h
> index b008a72..7088495 100644
> --- a/arch/arm64/include/asm/pci.h
> +++ b/arch/arm64/include/asm/pci.h
> @@ -10,6 +10,16 @@
>  #include <asm-generic/pci-bridge.h>
>  #include <asm-generic/pci-dma-compat.h>
> 
> +struct acpi_device;
> +
> +struct pci_controller {
> +#ifdef CONFIG_ACPI
> +       struct acpi_device *companion;  /* ACPI companion device */
> +#endif
> +       int             segment;        /* PCI domain */
> +       int             node;           /* NUMA node */
> +};
> +
>  #define PCIBIOS_MIN_IO         0x1000
>  #define PCIBIOS_MIN_MEM                0
> 
> 
> Thanks
> Hanjun

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

* Re: [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  2015-05-20  3:16     ` Jiang Liu
@ 2015-05-20  3:33       ` Hanjun Guo
  2015-05-22 11:23         ` Hanjun Guo
  0 siblings, 1 reply; 19+ messages in thread
From: Hanjun Guo @ 2015-05-20  3:33 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Len Brown
  Cc: Lv Zheng, LKML, linux-pci, linux-acpi, x86 @ kernel . org,
	linux-arm-kernel, Suthikulpanit, Suravee

+CC Suravee,

On 2015年05月20日 11:16, Jiang Liu wrote:
> On 2015/5/18 21:08, Hanjun Guo wrote:
>> Hi Jiang,
>>
>> On 2015年05月14日 16:56, Jiang Liu wrote:
>>> Introduce common interface acpi_pci_root_create() and related data
>>> structures to create PCI root bus for ACPI PCI host bridges. It will
>>> be used to kill duplicated arch specific code for IA64 and x86. It may
>>> also help ARM64 in future.
>>
>> As I commented in previous version, this patch will introduce
>> compile error on ACPI enabled ARM64 kernel because struct
>> pci_controller is not defined for ARM64, so how about adding
>> the following patch before this patch, or squash to this one,
>> does it make sense?
> Hi Hanjun,
> 	Thanks for fixing this building issue for ARM64. The patch
> is really what I want:). Will merge it into next version. With this
> patch applied, are there any other issues from ARM64 side?

Suravee is testing ARM64 PCI on top of your patch set, he can confirm
that if there are any other issues :) (Suravee has a real ARM64 hardware
in hand)

Thanks
Hanjun

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

* Re: [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  2015-05-20  3:33       ` Hanjun Guo
@ 2015-05-22 11:23         ` Hanjun Guo
  0 siblings, 0 replies; 19+ messages in thread
From: Hanjun Guo @ 2015-05-22 11:23 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Len Brown
  Cc: Lv Zheng, LKML, linux-pci, linux-acpi, x86 @ kernel . org,
	linux-arm-kernel, Suthikulpanit, Suravee

On 2015年05月20日 11:33, Hanjun Guo wrote:
> +CC Suravee,
>
> On 2015年05月20日 11:16, Jiang Liu wrote:
>> On 2015/5/18 21:08, Hanjun Guo wrote:
>>> Hi Jiang,
>>>
>>> On 2015年05月14日 16:56, Jiang Liu wrote:
>>>> Introduce common interface acpi_pci_root_create() and related data
>>>> structures to create PCI root bus for ACPI PCI host bridges. It will
>>>> be used to kill duplicated arch specific code for IA64 and x86. It may
>>>> also help ARM64 in future.
>>>
>>> As I commented in previous version, this patch will introduce
>>> compile error on ACPI enabled ARM64 kernel because struct
>>> pci_controller is not defined for ARM64, so how about adding
>>> the following patch before this patch, or squash to this one,
>>> does it make sense?
>> Hi Hanjun,
>>     Thanks for fixing this building issue for ARM64. The patch
>> is really what I want:). Will merge it into next version. With this
>> patch applied, are there any other issues from ARM64 side?
>
> Suravee is testing ARM64 PCI on top of your patch set, he can confirm
> that if there are any other issues :) (Suravee has a real ARM64 hardware
> in hand)

After confirmed with Suravee, this patch set works OK on ARM64
hardware for PCI hostbridge init, and can enumerate PCI devices
(adding some ARM64 related PCI patches) and works fine with legacy
interrupt, so to me, this patch set is good to go :)

For this patchset:

Tested-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>

I will add my Reviewed-by for some of patches later.

Thanks
Hanjun

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

* Re: [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space
  2015-05-14  8:56 ` [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
@ 2015-05-22 13:35   ` Hanjun Guo
  0 siblings, 0 replies; 19+ messages in thread
From: Hanjun Guo @ 2015-05-22 13:35 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Len Brown, Vivek Goyal, Thierry Reding,
	Jakub Sitnicki
  Cc: Lv Zheng, LKML, linux-pci, linux-acpi, x86 @ kernel . org,
	linux-arm-kernel

On 2015年05月14日 16:56, Jiang Liu wrote:
> Enhance ACPI resource parsing interfaces to support sparse IO space,
> which will be used to share common code between x86 and IA64 later.
>
> Tested-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>   drivers/acpi/resource.c |    9 ++++++---
>   include/linux/ioport.h  |    1 +
>   2 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
> index 8244f013f210..fdcc73dad2c1 100644
> --- a/drivers/acpi/resource.c
> +++ b/drivers/acpi/resource.c
> @@ -123,7 +123,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)
> +				      u8 io_decode, u8 translation_type)
>   {
>   	res->flags = IORESOURCE_IO;
>
> @@ -135,6 +135,8 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
>
>   	if (io_decode == ACPI_DECODE_16)
>   		res->flags |= IORESOURCE_IO_16BIT_ADDR;
> +	if (translation_type == ACPI_SPARSE_TRANSLATION)
> +		res->flags |= IORESOURCE_IO_SPARSE;
>   }
>
>   static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
> @@ -142,7 +144,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);
> +	acpi_dev_ioresource_flags(res, len, io_decode, 0);
>   }
>
>   /**
> @@ -227,7 +229,8 @@ static bool acpi_decode_space(struct resource_win *win,
>   		acpi_dev_memresource_flags(res, len, wp);
>   		break;
>   	case ACPI_IO_RANGE:
> -		acpi_dev_ioresource_flags(res, len, iodec);
> +		acpi_dev_ioresource_flags(res, len, iodec,
> +					  addr->info.io.translation_type);
>   		break;
>   	case ACPI_BUS_NUMBER_RANGE:
>   		res->flags = IORESOURCE_BUS;
> diff --git a/include/linux/ioport.h b/include/linux/ioport.h
> index 388e3ae94f7a..24bea087e7af 100644
> --- a/include/linux/ioport.h
> +++ b/include/linux/ioport.h
> @@ -94,6 +94,7 @@ struct resource {
>   /* PnP I/O specific bits (IORESOURCE_BITS) */
>   #define IORESOURCE_IO_16BIT_ADDR	(1<<0)
>   #define IORESOURCE_IO_FIXED		(1<<1)
> +#define IORESOURCE_IO_SPARSE		(1<<2)
>
>   /* PCI ROM control bits (IORESOURCE_BITS) */
>   #define IORESOURCE_ROM_ENABLE		(1<<0)	/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

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

* Re: [Patch v3 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge
  2015-05-14  8:56 ` [Patch v3 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
@ 2015-05-22 13:42   ` Hanjun Guo
  0 siblings, 0 replies; 19+ messages in thread
From: Hanjun Guo @ 2015-05-22 13:42 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Tony Luck, Fenghua Yu, Yinghai Lu
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel, linux-ia64

On 2015年05月14日 16:56, Jiang Liu wrote:
> Use common ACPI resource parsing interface to parse ACPI resources for
> PCI host bridge, so we could share more code between IA64 and x86.
> Later we will consolidate arch specific implementations into ACPI core.
>
> Tested-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>   arch/ia64/pci/pci.c |  414 ++++++++++++++++++++++++---------------------------
>   1 file changed, 193 insertions(+), 221 deletions(-)
>
> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
> index d4e162d35b34..23689d4c37ae 100644
> --- a/arch/ia64/pci/pci.c
> +++ b/arch/ia64/pci/pci.c
> @@ -115,29 +115,12 @@ struct pci_ops pci_root_ops = {
>   	.write = pci_write,
>   };
>
> -/* Called by ACPI when it finds a new root bus.  */
> -
> -static struct pci_controller *alloc_pci_controller(int seg)
> -{
> -	struct pci_controller *controller;
> -
> -	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
> -	if (!controller)
> -		return NULL;
> -
> -	controller->segment = seg;
> -	return controller;
> -}
> -
>   struct pci_root_info {
> +	struct pci_controller controller;
>   	struct acpi_device *bridge;
> -	struct pci_controller *controller;
>   	struct list_head resources;
> -	struct resource *res;
> -	resource_size_t *res_offset;
> -	unsigned int res_num;
>   	struct list_head io_resources;
> -	char *name;
> +	char name[16];
>   };
>
>   static unsigned int
> @@ -168,11 +151,11 @@ new_space (u64 phys_base, int sparse)
>   	return i;
>   }
>
> -static u64 add_io_space(struct pci_root_info *info,
> -			struct acpi_resource_address64 *addr)
> +static int add_io_space(struct device *dev, struct pci_root_info *info,
> +			struct resource_entry *entry)
>   {
>   	struct iospace_resource *iospace;
> -	struct resource *resource;
> +	struct resource *resource, *res = entry->res;
>   	char *name;
>   	unsigned long base, min, max, base_port;
>   	unsigned int sparse = 0, space_nr, len;
> @@ -180,27 +163,24 @@ static u64 add_io_space(struct pci_root_info *info,
>   	len = strlen(info->name) + 32;
>   	iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL);
>   	if (!iospace) {
> -		dev_err(&info->bridge->dev,
> -				"PCI: No memory for %s I/O port space\n",
> -				info->name);
> -		goto out;
> +		dev_err(dev, "PCI: No memory for %s I/O port space\n",
> +			info->name);
> +		return -ENOMEM;
>   	}
>
> -	name = (char *)(iospace + 1);
> -
> -	min = addr->address.minimum;
> -	max = min + addr->address.address_length - 1;
> -	if (addr->info.io.translation_type == ACPI_SPARSE_TRANSLATION)
> +	if (res->flags & IORESOURCE_IO_SPARSE)
>   		sparse = 1;
> -
> -	space_nr = new_space(addr->address.translation_offset, sparse);
> +	space_nr = new_space(entry->offset, sparse);
>   	if (space_nr == ~0)
>   		goto free_resource;
>
> +	name = (char *)(iospace + 1);
> +	min = res->start - entry->offset;
> +	max = res->end - entry->offset;
>   	base = __pa(io_space[space_nr].mmio_base);
>   	base_port = IO_SPACE_BASE(space_nr);
>   	snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->name,
> -		base_port + min, base_port + max);
> +		 base_port + min, base_port + max);
>
>   	/*
>   	 * The SDM guarantees the legacy 0-64K space is sparse, but if the
> @@ -216,153 +196,195 @@ static u64 add_io_space(struct pci_root_info *info,
>   	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
>   	resource->end   = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
>   	if (insert_resource(&iomem_resource, resource)) {
> -		dev_err(&info->bridge->dev,
> -				"can't allocate host bridge io space resource  %pR\n",
> -				resource);
> +		dev_err(dev,
> +			"can't allocate host bridge io space resource  %pR\n",
> +			resource);
>   		goto free_resource;
>   	}
>
> +	entry->offset = base_port;
> +	res->start = min + base_port;
> +	res->end = max + base_port;
>   	list_add_tail(&iospace->list, &info->io_resources);
> -	return base_port;
> +
> +	return 0;
>
>   free_resource:
>   	kfree(iospace);
> -out:
> -	return ~0;
> +	return -ENOSPC;
> +}
> +
> +/*
> + * An IO port or MMIO resource assigned to a PCI host bridge may be
> + * consumed by the host bridge itself or available to its child
> + * bus/devices. The ACPI specification defines a bit (Producer/Consumer)
> + * to tell whether the resource is consumed by the host bridge itself,
> + * but firmware hasn't used that bit consistently, so we can't rely on it.

If we make the firmware obey to the ACPI spec, and
...

> + *
> + * On x86 and IA64 platforms, all IO port and MMIO resources are assumed
> + * to be available to child bus/devices except one special case:
> + *     IO port [0xCF8-0xCFF] is consumed by the host bridge itself
> + *     to access PCI configuration space.
> + *
> + * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF].

This is not going to happen on ARM64, right?

but this question is not about the patch itself, so for this patch

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

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

* Re: [Patch v3 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource
  2015-05-14  8:56 ` [Patch v3 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
@ 2015-05-22 13:46   ` Hanjun Guo
  0 siblings, 0 replies; 19+ messages in thread
From: Hanjun Guo @ 2015-05-22 13:46 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Tony Luck, Fenghua Yu, Yinghai Lu
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	x86 @ kernel . org, linux-arm-kernel, linux-ia64

On 2015年05月14日 16:56, Jiang Liu wrote:
> Use common struct resource_entry to replace private
> struct iospace_resource.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>   arch/ia64/include/asm/pci.h |    5 -----
>   arch/ia64/pci/pci.c         |   17 ++++++++---------
>   2 files changed, 8 insertions(+), 14 deletions(-)
>
> diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
> index 52af5ed9f60b..5c10e0ec48d4 100644
> --- a/arch/ia64/include/asm/pci.h
> +++ b/arch/ia64/include/asm/pci.h
> @@ -83,11 +83,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
>   #define pci_legacy_read platform_pci_legacy_read
>   #define pci_legacy_write platform_pci_legacy_write
>
> -struct iospace_resource {
> -	struct list_head list;
> -	struct resource res;
> -};
> -
>   struct pci_controller {
>   	struct acpi_device *companion;
>   	void *iommu;
> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
> index 23689d4c37ae..4af1b52c7a44 100644
> --- a/arch/ia64/pci/pci.c
> +++ b/arch/ia64/pci/pci.c
> @@ -154,14 +154,14 @@ new_space (u64 phys_base, int sparse)
>   static int add_io_space(struct device *dev, struct pci_root_info *info,
>   			struct resource_entry *entry)
>   {
> -	struct iospace_resource *iospace;
> +	struct resource_entry *iospace;
>   	struct resource *resource, *res = entry->res;
>   	char *name;
>   	unsigned long base, min, max, base_port;
>   	unsigned int sparse = 0, space_nr, len;
>
>   	len = strlen(info->name) + 32;
> -	iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL);
> +	iospace = resource_list_create_entry(NULL, len);
>   	if (!iospace) {
>   		dev_err(dev, "PCI: No memory for %s I/O port space\n",
>   			info->name);
> @@ -190,7 +190,7 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
>   	if (space_nr == 0)
>   		sparse = 1;
>
> -	resource = &iospace->res;
> +	resource = iospace->res;
>   	resource->name  = name;
>   	resource->flags = IORESOURCE_MEM;
>   	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
> @@ -205,12 +205,12 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
>   	entry->offset = base_port;
>   	res->start = min + base_port;
>   	res->end = max + base_port;
> -	list_add_tail(&iospace->list, &info->io_resources);
> +	resource_list_add_tail(iospace, &info->io_resources);
>
>   	return 0;
>
>   free_resource:
> -	kfree(iospace);
> +	resource_list_free_entry(iospace);
>   	return -ENOSPC;
>   }
>
> @@ -369,12 +369,11 @@ static void add_resources(struct pci_root_info *info, struct device *dev)
>   static void __release_pci_root_info(struct pci_root_info *info)
>   {
>   	struct resource *res;
> -	struct iospace_resource *iospace, *tmp;
>   	struct resource_entry *entry, *tentry;
>
> -	list_for_each_entry_safe(iospace, tmp, &info->io_resources, list) {
> -		release_resource(&iospace->res);
> -		kfree(iospace);
> +	resource_list_for_each_entry_safe(entry, tentry, &info->io_resources) {
> +		release_resource(entry->res);
> +		resource_list_destroy_entry(entry);
>   	}
>
>   	resource_list_for_each_entry_safe(entry, tentry, &info->resources) {


Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

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

* Re: [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
  2015-05-14  8:56 ` [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
  2015-05-18 13:08   ` Hanjun Guo
@ 2015-05-22 13:49   ` Hanjun Guo
  1 sibling, 0 replies; 19+ messages in thread
From: Hanjun Guo @ 2015-05-22 13:49 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Len Brown
  Cc: Lv Zheng, LKML, linux-pci, linux-acpi, x86 @ kernel . org,
	linux-arm-kernel

On 2015年05月14日 16:56, Jiang Liu wrote:
> Introduce common interface acpi_pci_root_create() and related data
> structures to create PCI root bus for ACPI PCI host bridges. It will
> be used to kill duplicated arch specific code for IA64 and x86. It may
> also help ARM64 in future.
>
> Tested-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>   drivers/acpi/pci_root.c  |  200 ++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/pci-acpi.h |   23 ++++++
>   2 files changed, 223 insertions(+)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 1b5569c092c6..22d0cb799ef1 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -656,6 +656,206 @@ static void acpi_pci_root_remove(struct acpi_device *device)
>   	kfree(root);
>   }
>
> +static void acpi_pci_root_validate_resources(struct device *dev,
> +					     struct list_head *resources,
> +					     unsigned long type)
> +{
> +	LIST_HEAD(list);
> +	struct resource *res1, *res2, *root = NULL;
> +	struct resource_entry *tmp, *entry, *entry2;
> +
> +	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
> +	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
> +
> +	list_splice_init(resources, &list);
> +	resource_list_for_each_entry_safe(entry, tmp, &list) {
> +		bool free = false;
> +		resource_size_t end;
> +
> +		res1 = entry->res;
> +		if (!(res1->flags & type))
> +			goto next;
> +
> +		/* Exclude non-addressable range or non-addressable portion */
> +		end = min(res1->end, root->end);
> +		if (end <= res1->start) {
> +			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
> +				 res1);
> +			free = true;
> +			goto next;
> +		} else if (res1->end != end) {
> +			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
> +				 res1, (unsigned long long)end + 1,
> +				 (unsigned long long)res1->end);
> +			res1->end = end;
> +		}
> +
> +		resource_list_for_each_entry(entry2, resources) {
> +			res2 = entry2->res;
> +			if (!(res2->flags & type))
> +				continue;
> +
> +			/*
> +			 * I don't like throwing away windows because then
> +			 * our resources no longer match the ACPI _CRS, but
> +			 * the kernel resource tree doesn't allow overlaps.
> +			 */
> +			if (resource_overlaps(res1, res2)) {
> +				res2->start = min(res1->start, res2->start);
> +				res2->end = max(res1->end, res2->end);
> +				dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
> +					 res2, res1);
> +				free = true;
> +				goto next;
> +			}
> +		}
> +
> +next:
> +		resource_list_del(entry);
> +		if (free)
> +			resource_list_free_entry(entry);
> +		else
> +			resource_list_add_tail(entry, resources);
> +	}
> +}
> +
> +static int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
> +{
> +	int ret;
> +	struct list_head *list = &info->resources;
> +	struct acpi_device *device = info->bridge;
> +	struct resource_entry *entry, *tmp;
> +	unsigned long flags;
> +
> +	flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
> +	ret = acpi_dev_get_resources(device, list,
> +				     acpi_dev_filter_resource_type_cb,
> +				     (void *)flags);
> +	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_safe(entry, tmp, list) {
> +			if (entry->res->flags & IORESOURCE_DISABLED)
> +				resource_list_destroy_entry(entry);
> +			else
> +				entry->res->name = info->name;
> +		}
> +		acpi_pci_root_validate_resources(&device->dev, list,
> +						 IORESOURCE_MEM);
> +		acpi_pci_root_validate_resources(&device->dev, list,
> +						 IORESOURCE_IO);
> +	}
> +
> +	return ret;
> +}
> +
> +static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
> +{
> +	struct resource_entry *entry, *tmp;
> +	struct resource *res, *conflict, *root = NULL;
> +
> +	resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
> +		res = entry->res;
> +		if (res->flags & IORESOURCE_MEM)
> +			root = &iomem_resource;
> +		else if (res->flags & IORESOURCE_IO)
> +			root = &ioport_resource;
> +		else
> +			continue;
> +
> +		conflict = insert_resource_conflict(root, res);
> +		if (conflict) {
> +			dev_info(&info->bridge->dev,
> +				 "ignoring host bridge window %pR (conflicts with %s %pR)\n",
> +				 res, conflict->name, conflict);
> +			resource_list_destroy_entry(entry);
> +		}
> +	}
> +}
> +
> +static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
> +{
> +	struct resource *res;
> +	struct resource_entry *entry, *tmp;
> +
> +	if (!info)
> +		return;
> +
> +	resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
> +		res = entry->res;
> +		if (res->parent &&
> +		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
> +			release_resource(res);
> +		resource_list_destroy_entry(entry);
> +	}
> +
> +	info->ops->release_info(info);
> +}
> +
> +static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
> +{
> +	struct resource *res;
> +	struct resource_entry *entry;
> +
> +	resource_list_for_each_entry(entry, &bridge->windows) {
> +		res = entry->res;
> +		if (res->parent &&
> +		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
> +			release_resource(res);
> +	}
> +	__acpi_pci_root_release_info(bridge->release_data);
> +}
> +
> +struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
> +				     struct acpi_pci_root_ops *ops,
> +				     struct acpi_pci_root_info *info)
> +{
> +	int ret, busnum = root->secondary.start;
> +	struct acpi_device *device = root->device;
> +	struct pci_bus *bus;
> +
> +	info->controller.segment = root->segment;
> +	info->controller.node = acpi_get_node(device->handle);
> +	info->controller.companion = device;
> +	info->root = root;
> +	info->bridge = device;
> +	info->ops = ops;
> +	INIT_LIST_HEAD(&info->resources);
> +	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> +		 info->controller.segment, busnum);
> +
> +	if (ops->init_info && ops->init_info(info))
> +		goto out_release_info;
> +	ret = acpi_pci_probe_root_resources(info);
> +	if (ops->prepare_resources)
> +		ret = ops->prepare_resources(info, ret);
> +	if (ret < 0)
> +		goto out_release_info;
> +	else if (ret > 0)
> +		pci_acpi_root_add_resources(info);
> +	pci_add_resource(&info->resources, &root->secondary);
> +
> +	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> +				  &info->controller, &info->resources);
> +	if (bus) {
> +		pci_scan_child_bus(bus);
> +		pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
> +					    acpi_pci_root_release_info, info);
> +		if (info->controller.node != NUMA_NO_NODE)
> +			dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n",
> +				   info->controller.node);
> +		return bus;
> +	}
> +
> +out_release_info:
> +	__acpi_pci_root_release_info(info);
> +	return NULL;
> +}
> +
>   void __init acpi_pci_root_init(void)
>   {
>   	acpi_hest_init();
> diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> index a965efa52152..685ccc4c3170 100644
> --- a/include/linux/pci-acpi.h
> +++ b/include/linux/pci-acpi.h
> @@ -52,6 +52,29 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
>   	return ACPI_HANDLE(dev);
>   }
>
> +struct acpi_pci_root;
> +struct acpi_pci_root_ops;
> +
> +struct acpi_pci_root_info {
> +	struct pci_controller		controller;
> +	struct acpi_pci_root		*root;
> +	struct acpi_device		*bridge;
> +	struct acpi_pci_root_ops	*ops;
> +	struct list_head		resources;
> +	char				name[16];
> +};
> +
> +struct acpi_pci_root_ops {
> +	struct pci_ops *pci_ops;
> +	int (*init_info)(struct acpi_pci_root_info *info);
> +	void (*release_info)(struct acpi_pci_root_info *info);
> +	int (*prepare_resources)(struct acpi_pci_root_info *info, int status);
> +};
> +
> +extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
> +					    struct acpi_pci_root_ops *ops,
> +					    struct acpi_pci_root_info *info);
> +
>   void acpi_pci_add_bus(struct pci_bus *bus);
>   void acpi_pci_remove_bus(struct pci_bus *bus);

As long as you added my ARM64 struct pci_controller patch,

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

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

* Re: [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
  2015-05-14  8:56 ` [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
@ 2015-05-22 13:55   ` Hanjun Guo
  2015-06-02  5:56     ` Jiang Liu
  0 siblings, 1 reply; 19+ messages in thread
From: Hanjun Guo @ 2015-05-22 13:55 UTC (permalink / raw)
  To: Jiang Liu, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	linux-arm-kernel

On 2015年05月14日 16:56, Jiang Liu wrote:
> Use common interface to simplify ACPI PCI host bridge implementation.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>   arch/x86/pci/acpi.c |  292 +++++++++++++++------------------------------------
>   1 file changed, 85 insertions(+), 207 deletions(-)
>
[...]
> -static void release_pci_root_info(struct pci_host_bridge *bridge)
> +static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
>   {
> -	struct resource *res;
> -	struct resource_entry *entry;
> -	struct pci_root_info *info = bridge->release_data;
> -
> -	resource_list_for_each_entry(entry, &bridge->windows) {
> -		res = entry->res;
> -		if (res->parent &&
> -		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
> -			release_resource(res);
> -	}
> -
> -	teardown_mcfg_map(info);
> -	kfree(info);
> +	teardown_mcfg_map(ci);
> +	kfree(ci);

Implicit pointer cast? I think add a comment here that %p of ci
is same as %p of info would be helpful for review and easy understood.

other than that,

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

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

* Re: [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
  2015-05-22 13:55   ` Hanjun Guo
@ 2015-06-02  5:56     ` Jiang Liu
  2015-06-02  6:29       ` Hanjun Guo
  0 siblings, 1 reply; 19+ messages in thread
From: Jiang Liu @ 2015-06-02  5:56 UTC (permalink / raw)
  To: Hanjun Guo, Rafael J . Wysocki, Bjorn Helgaas, Marc Zyngier,
	Yijing Wang, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	linux-arm-kernel

On 2015/5/22 21:55, Hanjun Guo wrote:
> On 2015年05月14日 16:56, Jiang Liu wrote:
>> Use common interface to simplify ACPI PCI host bridge implementation.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>   arch/x86/pci/acpi.c |  292
>> +++++++++++++++------------------------------------
>>   1 file changed, 85 insertions(+), 207 deletions(-)
>>
> [...]
>> -static void release_pci_root_info(struct pci_host_bridge *bridge)
>> +static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
>>   {
>> -    struct resource *res;
>> -    struct resource_entry *entry;
>> -    struct pci_root_info *info = bridge->release_data;
>> -
>> -    resource_list_for_each_entry(entry, &bridge->windows) {
>> -        res = entry->res;
>> -        if (res->parent &&
>> -            (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
>> -            release_resource(res);
>> -    }
>> -
>> -    teardown_mcfg_map(info);
>> -    kfree(info);
>> +    teardown_mcfg_map(ci);
>> +    kfree(ci);
> 
> Implicit pointer cast? I think add a comment here that %p of ci
> is same as %p of info would be helpful for review and easy understood.

Good point, will change as:
	kfree(container_of(ci, struct pci_root_info, common));
Thanks!
Gerry

> 
> other than that,
> 
> Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
> 
> Thanks
> Hanjun

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

* Re: [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
  2015-06-02  5:56     ` Jiang Liu
@ 2015-06-02  6:29       ` Hanjun Guo
  0 siblings, 0 replies; 19+ messages in thread
From: Hanjun Guo @ 2015-06-02  6:29 UTC (permalink / raw)
  To: Jiang Liu, Hanjun Guo, Rafael J . Wysocki, Bjorn Helgaas,
	Marc Zyngier, Yijing Wang, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86
  Cc: Lv Zheng, lenb @ kernel . org, LKML, linux-pci, linux-acpi,
	linux-arm-kernel

On 2015/6/2 13:56, Jiang Liu wrote:
> On 2015/5/22 21:55, Hanjun Guo wrote:
>> On 2015年05月14日 16:56, Jiang Liu wrote:
>>> Use common interface to simplify ACPI PCI host bridge implementation.
>>>
>>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>>> ---
>>>   arch/x86/pci/acpi.c |  292
>>> +++++++++++++++------------------------------------
>>>   1 file changed, 85 insertions(+), 207 deletions(-)
>>>
>> [...]
>>> -static void release_pci_root_info(struct pci_host_bridge *bridge)
>>> +static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
>>>   {
>>> -    struct resource *res;
>>> -    struct resource_entry *entry;
>>> -    struct pci_root_info *info = bridge->release_data;
>>> -
>>> -    resource_list_for_each_entry(entry, &bridge->windows) {
>>> -        res = entry->res;
>>> -        if (res->parent &&
>>> -            (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
>>> -            release_resource(res);
>>> -    }
>>> -
>>> -    teardown_mcfg_map(info);
>>> -    kfree(info);
>>> +    teardown_mcfg_map(ci);
>>> +    kfree(ci);
>> Implicit pointer cast? I think add a comment here that %p of ci
>> is same as %p of info would be helpful for review and easy understood.
> Good point, will change as:
> 	kfree(container_of(ci, struct pci_root_info, common));

This way is better :)

Thanks
Hanjun


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

end of thread, other threads:[~2015-06-02  6:32 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-14  8:56 [Patch v3 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
2015-05-14  8:56 ` [Patch v3 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
2015-05-22 13:35   ` Hanjun Guo
2015-05-14  8:56 ` [Patch v3 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
2015-05-22 13:42   ` Hanjun Guo
2015-05-14  8:56 ` [Patch v3 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
2015-05-22 13:46   ` Hanjun Guo
2015-05-14  8:56 ` [Patch v3 4/7] x86/PCI: Rename struct pci_sysdata as struct pci_controller Jiang Liu
2015-05-14  8:56 ` [Patch v3 5/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
2015-05-18 13:08   ` Hanjun Guo
2015-05-20  3:16     ` Jiang Liu
2015-05-20  3:33       ` Hanjun Guo
2015-05-22 11:23         ` Hanjun Guo
2015-05-22 13:49   ` Hanjun Guo
2015-05-14  8:56 ` [Patch v3 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
2015-05-22 13:55   ` Hanjun Guo
2015-06-02  5:56     ` Jiang Liu
2015-06-02  6:29       ` Hanjun Guo
2015-05-14  8:56 ` [Patch v3 7/7] ia64/PCI/ACPI: " 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).