All of lore.kernel.org
 help / color / mirror / Atom feed
* [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core
@ 2015-10-14  6:29 Jiang Liu
  2015-10-14  6:29 ` [Patch v7 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
                   ` (7 more replies)
  0 siblings, 8 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Liu Jiang, linux-acpi, linux-pci, linux-kernel, x86

From: Liu Jiang <jiang.liu@linux.intel.com>

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. And a patch set based on previous version to support
ACPI based PCIe host bridge on ARM64 has been posted at:
https://lkml.org/lkml/2015/5/26/207

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

V6->V7:
1) Improve commit message according to Bjorn's suggestion.
2) Move arch specific logic(code) from ACPI core into arch code
   according to Bjorn's review comments.

V5->V6:
1) Patch 5 to reset domain number to 0 when pci_ignore_seg is set
2) Remove parameter segment and node from function acpi_pci_root_create(),
   as suggested by Lorenzo and Bjorn.
V4-V5:
1) As suggested by Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>, do not
   introduce "struct pci_controller" into generic drivers/acpi/pci_root.c,
   so ARM64 doesn't need to define a useless structure. And it simplifies
   code a little too.

V3->V4:
1) Add patch[05/08] support solve building issue on ARM64
2) Solve an implicitly pointer cast issue.
3) Rebase to latest mainstream kernel

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
  PCI/ACPI: Add interface acpi_pci_root_create()
  ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is
    set
  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         |  368 ++++++++++++-------------------------------
 arch/x86/pci/acpi.c         |  296 +++++++++++-----------------------
 drivers/acpi/pci_root.c     |  204 ++++++++++++++++++++++++
 drivers/acpi/resource.c     |    9 +-
 include/linux/ioport.h      |    1 +
 include/linux/pci-acpi.h    |   24 +++
 7 files changed, 423 insertions(+), 484 deletions(-)

-- 
1.7.10.4

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

* [Patch v7 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-14  6:29 ` [Patch v7 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

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>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Liu Jiang <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 15d22db05054..cdc5c2599beb 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -119,7 +119,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;
 
@@ -131,6 +131,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,
@@ -138,7 +140,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);
 }
 
 /**
@@ -231,7 +233,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] 56+ messages in thread

* [Patch v7 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
  2015-10-14  6:29 ` [Patch v7 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-14  6:29 ` [Patch v7 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

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>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Liu Jiang <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 7cc3be9fa7c6..d20db9e48014 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] 56+ messages in thread

* [Patch v7 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
  2015-10-14  6:29 ` [Patch v7 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
  2015-10-14  6:29 ` [Patch v7 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-14  6:29 ` [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create() Jiang Liu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

Use common struct resource_entry to replace private
struct iospace_resource.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Liu Jiang <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 36d2c1e3928b..07039d168f37 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -64,11 +64,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 d20db9e48014..b1846b891ea5 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] 56+ messages in thread

* [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (2 preceding siblings ...)
  2015-10-14  6:29 ` [Patch v7 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-15 20:47   ` Bjorn Helgaas
                     ` (2 more replies)
  2015-10-14  6:29 ` [Patch v7 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
                   ` (3 subsequent siblings)
  7 siblings, 3 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

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.

Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
---
 drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci-acpi.h |   24 ++++++
 2 files changed, 228 insertions(+)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 393706a5261b..850d7bf0c873 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -652,6 +652,210 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 	kfree(root);
 }
 
+/*
+ * Following code to support acpi_pci_root_create() is copied from
+ * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
+ * and ARM64.
+ */
+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);
+	}
+}
+
+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,
+				     void *sysdata)
+{
+	int ret, busnum = root->secondary.start;
+	struct acpi_device *device = root->device;
+	int node = acpi_get_node(device->handle);
+	struct pci_bus *bus;
+
+	info->root = root;
+	info->bridge = device;
+	info->ops = ops;
+	INIT_LIST_HEAD(&info->resources);
+	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
+		 root->segment, busnum);
+
+	if (ops->init_info && ops->init_info(info))
+		goto out_release_info;
+	if (ops->prepare_resources)
+		ret = ops->prepare_resources(info);
+	else
+		ret = acpi_pci_probe_root_resources(info);
+	if (ret < 0)
+		goto out_release_info;
+
+	pci_acpi_root_add_resources(info);
+	pci_add_resource(&info->resources, &root->secondary);
+	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
+				  sysdata, &info->resources);
+	if (!bus)
+		goto out_release_info;
+
+	pci_scan_child_bus(bus);
+	pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
+				    acpi_pci_root_release_info, info);
+	if (node != NUMA_NO_NODE)
+		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", 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..89ab0572dbc6 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -52,6 +52,30 @@ 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 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);
+};
+
+extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
+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 *sd);
+
 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] 56+ messages in thread

* [Patch v7 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (3 preceding siblings ...)
  2015-10-14  6:29 ` [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create() Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-14  6:29 ` [Patch v7 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set to keep
consistence between ACPI PCI root device and PCI host bridge device.

Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
---
 arch/x86/pci/acpi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index ff9911707160..5bc018559cc4 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -401,7 +401,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	int node;
 
 	if (pci_ignore_seg)
-		domain = 0;
+		root->segment = domain = 0;
 
 	if (domain && !pci_domains_supported) {
 		printk(KERN_WARNING "pci_bus %04x:%02x: "
-- 
1.7.10.4


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

* [Patch v7 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (4 preceding siblings ...)
  2015-10-14  6:29 ` [Patch v7 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-15 20:46   ` Bjorn Helgaas
  2015-10-14  6:29 ` [Patch v7 7/7] ia64/PCI/ACPI: " Jiang Liu
  2015-10-15 20:48 ` [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Bjorn Helgaas
  7 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

Use common interface to simplify ACPI PCI host bridge implementation.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
---
 arch/x86/pci/acpi.c |  294 +++++++++++++++------------------------------------
 1 file changed, 87 insertions(+), 207 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5bc018559cc4..3cd69832d7f4 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -4,16 +4,15 @@
 #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 acpi_pci_root_info common;
 	struct pci_sysdata sd;
 #ifdef	CONFIG_PCI_MMCONFIG
 	bool mcfg_added;
-	u16 segment;
 	u8 start_bus;
 	u8 end_bus;
 #endif
@@ -178,15 +177,18 @@ 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;
+	int result, seg;
+	struct pci_root_info *info;
+	struct acpi_pci_root *root = ci->root;
+	struct device *dev = &ci->bridge->dev;
 
-	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;
+	seg = info->sd.domain;
 
 	/* return success if MMCFG is not in use */
 	if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
@@ -195,7 +197,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)
@@ -208,134 +211,55 @@ 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(info->sd.domain,
+				    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;
-			}
-		}
+	int busnum = root->secondary.start;
+	struct acpi_device *device = root->device;
+	int node = acpi_get_node(device->handle);
 
-next:
-		resource_list_del(entry);
-		if (free)
-			resource_list_free_entry(entry);
-		else
-			resource_list_add_tail(entry, crs_res);
+	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);
-		}
-	}
-
-	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(container_of(ci, struct pci_root_info, common));
 }
 
 /*
@@ -358,47 +282,44 @@ 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 ret;
+	struct acpi_device *device = ci->bridge;
+	int busnum = ci->root->secondary.start;
 	struct resource_entry *entry, *tmp;
+	int status;
 
-	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))
+	status = acpi_pci_probe_root_resources(ci);
+	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_sysdata *sd;
-	int node;
 
 	if (pci_ignore_seg)
 		root->segment = domain = 0;
@@ -410,71 +331,33 @@ 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->domain = 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);
-	} else {
-		/* insert busn res at first */
-		pci_add_resource(&resources,  &root->secondary);
+		struct pci_sysdata sd = {
+			.domain = domain,
+			.node = node,
+			.companion = root->device
+		};
 
-		/*
-		 * _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);
+		memcpy(bus->sysdata, &sd, sizeof(sd));
+	} else {
+		struct pci_root_info *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 {
+			info->sd.domain = domain;
+			info->sd.node = node;
+			info->sd.companion = root->device;
+			bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
+						   &info->common, &info->sd);
 		}
 	}
 
@@ -487,9 +370,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] 56+ messages in thread

* [Patch v7 7/7] ia64/PCI/ACPI: Use common interface to support PCI host bridge
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (5 preceding siblings ...)
  2015-10-14  6:29 ` [Patch v7 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
@ 2015-10-14  6:29 ` Jiang Liu
  2015-10-15 20:48 ` [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Bjorn Helgaas
  7 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-14  6:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: Jiang Liu, linux-acpi, linux-pci, linux-kernel, x86

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>
Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
---
 arch/ia64/pci/pci.c |  235 +++++++++++----------------------------------------
 1 file changed, 48 insertions(+), 187 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index b1846b891ea5..8f6ac2f8ae4c 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -116,15 +116,12 @@ struct pci_ops pci_root_ops = {
 };
 
 struct pci_root_info {
+	struct acpi_pci_root_info common;
 	struct pci_controller controller;
-	struct acpi_device *bridge;
-	struct list_head resources;
 	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 +157,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 +176,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 +231,81 @@ 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 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;
+	int status;
+
+	status = acpi_pci_probe_root_resources(ci);
+	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,
 			"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.segment = root->segment;
 	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, &info->controller);
 }
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-- 
1.7.10.4

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

* Re: [Patch v7 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
  2015-10-14  6:29 ` [Patch v7 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
@ 2015-10-15 20:46   ` Bjorn Helgaas
  0 siblings, 0 replies; 56+ messages in thread
From: Bjorn Helgaas @ 2015-10-15 20:46 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Wed, Oct 14, 2015 at 02:29:41PM +0800, Jiang Liu wrote:
> Use common interface to simplify ACPI PCI host bridge implementation.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>

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

> ---
>  arch/x86/pci/acpi.c |  294 +++++++++++++++------------------------------------
>  1 file changed, 87 insertions(+), 207 deletions(-)
> 
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index 5bc018559cc4..3cd69832d7f4 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -4,16 +4,15 @@
>  #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 acpi_pci_root_info common;
>  	struct pci_sysdata sd;
>  #ifdef	CONFIG_PCI_MMCONFIG
>  	bool mcfg_added;
> -	u16 segment;
>  	u8 start_bus;
>  	u8 end_bus;
>  #endif
> @@ -178,15 +177,18 @@ 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;
> +	int result, seg;
> +	struct pci_root_info *info;
> +	struct acpi_pci_root *root = ci->root;
> +	struct device *dev = &ci->bridge->dev;
>  
> -	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;
> +	seg = info->sd.domain;
>  
>  	/* return success if MMCFG is not in use */
>  	if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
> @@ -195,7 +197,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)
> @@ -208,134 +211,55 @@ 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(info->sd.domain,
> +				    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;
> -			}
> -		}
> +	int busnum = root->secondary.start;
> +	struct acpi_device *device = root->device;
> +	int node = acpi_get_node(device->handle);
>  
> -next:
> -		resource_list_del(entry);
> -		if (free)
> -			resource_list_free_entry(entry);
> -		else
> -			resource_list_add_tail(entry, crs_res);
> +	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);
> -		}
> -	}
> -
> -	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(container_of(ci, struct pci_root_info, common));
>  }
>  
>  /*
> @@ -358,47 +282,44 @@ 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 ret;
> +	struct acpi_device *device = ci->bridge;
> +	int busnum = ci->root->secondary.start;
>  	struct resource_entry *entry, *tmp;
> +	int status;
>  
> -	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))
> +	status = acpi_pci_probe_root_resources(ci);
> +	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_sysdata *sd;
> -	int node;
>  
>  	if (pci_ignore_seg)
>  		root->segment = domain = 0;
> @@ -410,71 +331,33 @@ 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->domain = 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);
> -	} else {
> -		/* insert busn res at first */
> -		pci_add_resource(&resources,  &root->secondary);
> +		struct pci_sysdata sd = {
> +			.domain = domain,
> +			.node = node,
> +			.companion = root->device
> +		};
>  
> -		/*
> -		 * _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);
> +		memcpy(bus->sysdata, &sd, sizeof(sd));
> +	} else {
> +		struct pci_root_info *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 {
> +			info->sd.domain = domain;
> +			info->sd.node = node;
> +			info->sd.companion = root->device;
> +			bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
> +						   &info->common, &info->sd);
>  		}
>  	}
>  
> @@ -487,9 +370,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
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-14  6:29 ` [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create() Jiang Liu
@ 2015-10-15 20:47   ` Bjorn Helgaas
  2015-10-21  9:57   ` Tomasz Nowicki
  2015-11-05 14:21   ` Tomasz Nowicki
  2 siblings, 0 replies; 56+ messages in thread
From: Bjorn Helgaas @ 2015-10-15 20:47 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Wed, Oct 14, 2015 at 02:29:39PM +0800, 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.
> 
> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Tested-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>

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

> ---
>  drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pci-acpi.h |   24 ++++++
>  2 files changed, 228 insertions(+)
> 
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 393706a5261b..850d7bf0c873 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -652,6 +652,210 @@ static void acpi_pci_root_remove(struct acpi_device *device)
>  	kfree(root);
>  }
>  
> +/*
> + * Following code to support acpi_pci_root_create() is copied from
> + * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
> + * and ARM64.
> + */
> +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);
> +	}
> +}
> +
> +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,
> +				     void *sysdata)
> +{
> +	int ret, busnum = root->secondary.start;
> +	struct acpi_device *device = root->device;
> +	int node = acpi_get_node(device->handle);
> +	struct pci_bus *bus;
> +
> +	info->root = root;
> +	info->bridge = device;
> +	info->ops = ops;
> +	INIT_LIST_HEAD(&info->resources);
> +	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> +		 root->segment, busnum);
> +
> +	if (ops->init_info && ops->init_info(info))
> +		goto out_release_info;
> +	if (ops->prepare_resources)
> +		ret = ops->prepare_resources(info);
> +	else
> +		ret = acpi_pci_probe_root_resources(info);
> +	if (ret < 0)
> +		goto out_release_info;
> +
> +	pci_acpi_root_add_resources(info);
> +	pci_add_resource(&info->resources, &root->secondary);
> +	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> +				  sysdata, &info->resources);
> +	if (!bus)
> +		goto out_release_info;
> +
> +	pci_scan_child_bus(bus);
> +	pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
> +				    acpi_pci_root_release_info, info);
> +	if (node != NUMA_NO_NODE)
> +		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", 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..89ab0572dbc6 100644
> --- a/include/linux/pci-acpi.h
> +++ b/include/linux/pci-acpi.h
> @@ -52,6 +52,30 @@ 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 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);
> +};
> +
> +extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info);
> +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 *sd);
> +
>  void acpi_pci_add_bus(struct pci_bus *bus);
>  void acpi_pci_remove_bus(struct pci_bus *bus);
>  
> -- 
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core
  2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
                   ` (6 preceding siblings ...)
  2015-10-14  6:29 ` [Patch v7 7/7] ia64/PCI/ACPI: " Jiang Liu
@ 2015-10-15 20:48 ` Bjorn Helgaas
  2015-10-15 21:49   ` Rafael J. Wysocki
  7 siblings, 1 reply; 56+ messages in thread
From: Bjorn Helgaas @ 2015-10-15 20:48 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Wed, Oct 14, 2015 at 02:29:35PM +0800, Jiang Liu wrote:
> From: Liu Jiang <jiang.liu@linux.intel.com>
> 
> 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. And a patch set based on previous version to support
> ACPI based PCIe host bridge on ARM64 has been posted at:
> https://lkml.org/lkml/2015/5/26/207
> 
> It's based on latest mainstream kernel. It passes Fengguang's 0day test
> suite and has been tested on two IA64 platforms and one x86 platform.
> 
> V6->V7:
> 1) Improve commit message according to Bjorn's suggestion.
> 2) Move arch specific logic(code) from ACPI core into arch code
>    according to Bjorn's review comments.

Thanks for cleaning this up; I think it looks much better.

As far as I'm concerned, this series is ready to go.  I assume Rafael
will merge it.

> V5->V6:
> 1) Patch 5 to reset domain number to 0 when pci_ignore_seg is set
> 2) Remove parameter segment and node from function acpi_pci_root_create(),
>    as suggested by Lorenzo and Bjorn.
> V4-V5:
> 1) As suggested by Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>, do not
>    introduce "struct pci_controller" into generic drivers/acpi/pci_root.c,
>    so ARM64 doesn't need to define a useless structure. And it simplifies
>    code a little too.
> 
> V3->V4:
> 1) Add patch[05/08] support solve building issue on ARM64
> 2) Solve an implicitly pointer cast issue.
> 3) Rebase to latest mainstream kernel
> 
> 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
>   PCI/ACPI: Add interface acpi_pci_root_create()
>   ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is
>     set
>   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         |  368 ++++++++++++-------------------------------
>  arch/x86/pci/acpi.c         |  296 +++++++++++-----------------------
>  drivers/acpi/pci_root.c     |  204 ++++++++++++++++++++++++
>  drivers/acpi/resource.c     |    9 +-
>  include/linux/ioport.h      |    1 +
>  include/linux/pci-acpi.h    |   24 +++
>  7 files changed, 423 insertions(+), 484 deletions(-)
> 
> -- 
> 1.7.10.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core
  2015-10-15 20:48 ` [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Bjorn Helgaas
@ 2015-10-15 21:49   ` Rafael J. Wysocki
  2015-10-16  1:56     ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Rafael J. Wysocki @ 2015-10-15 21:49 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Thursday, October 15, 2015 03:48:29 PM Bjorn Helgaas wrote:
> On Wed, Oct 14, 2015 at 02:29:35PM +0800, Jiang Liu wrote:
> > From: Liu Jiang <jiang.liu@linux.intel.com>
> > 
> > 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. And a patch set based on previous version to support
> > ACPI based PCIe host bridge on ARM64 has been posted at:
> > https://lkml.org/lkml/2015/5/26/207
> > 
> > It's based on latest mainstream kernel. It passes Fengguang's 0day test
> > suite and has been tested on two IA64 platforms and one x86 platform.
> > 
> > V6->V7:
> > 1) Improve commit message according to Bjorn's suggestion.
> > 2) Move arch specific logic(code) from ACPI core into arch code
> >    according to Bjorn's review comments.
> 
> Thanks for cleaning this up; I think it looks much better.
> 
> As far as I'm concerned, this series is ready to go.  I assume Rafael
> will merge it.

Yes, I'm going to do that.

Thanks a lot for your help with the review!

Rafael


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

* Re: [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core
  2015-10-15 21:49   ` Rafael J. Wysocki
@ 2015-10-16  1:56     ` Jiang Liu
  0 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-10-16  1:56 UTC (permalink / raw)
  To: Rafael J. Wysocki, Bjorn Helgaas
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 2015/10/16 5:49, Rafael J. Wysocki wrote:
> On Thursday, October 15, 2015 03:48:29 PM Bjorn Helgaas wrote:
>> On Wed, Oct 14, 2015 at 02:29:35PM +0800, Jiang Liu wrote:
>>> From: Liu Jiang <jiang.liu@linux.intel.com>
>>>
>>> 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. And a patch set based on previous version to support
>>> ACPI based PCIe host bridge on ARM64 has been posted at:
>>> https://lkml.org/lkml/2015/5/26/207
>>>
>>> It's based on latest mainstream kernel. It passes Fengguang's 0day test
>>> suite and has been tested on two IA64 platforms and one x86 platform.
>>>
>>> V6->V7:
>>> 1) Improve commit message according to Bjorn's suggestion.
>>> 2) Move arch specific logic(code) from ACPI core into arch code
>>>    according to Bjorn's review comments.
>>
>> Thanks for cleaning this up; I think it looks much better.
>>
>> As far as I'm concerned, this series is ready to go.  I assume Rafael
>> will merge it.
> 
> Yes, I'm going to do that.
> 
> Thanks a lot for your help with the review!
Thanks Bjorn and Rafael for review!


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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-14  6:29 ` [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create() Jiang Liu
  2015-10-15 20:47   ` Bjorn Helgaas
@ 2015-10-21  9:57   ` Tomasz Nowicki
  2015-10-21 11:02     ` Liviu Dudau
  2015-11-05 14:21   ` Tomasz Nowicki
  2 siblings, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-10-21  9:57 UTC (permalink / raw)
  To: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau
  Cc: linux-acpi, linux-pci, linux-kernel, x86

On 14.10.2015 08:29, 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.
>
> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Tested-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> ---
>   drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/pci-acpi.h |   24 ++++++
>   2 files changed, 228 insertions(+)
>

[...]

> +
> +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 *sysdata)
> +{
> +	int ret, busnum = root->secondary.start;
> +	struct acpi_device *device = root->device;
> +	int node = acpi_get_node(device->handle);
> +	struct pci_bus *bus;
> +
> +	info->root = root;
> +	info->bridge = device;
> +	info->ops = ops;
> +	INIT_LIST_HEAD(&info->resources);
> +	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> +		 root->segment, busnum);
> +
> +	if (ops->init_info && ops->init_info(info))
> +		goto out_release_info;
> +	if (ops->prepare_resources)
> +		ret = ops->prepare_resources(info);
> +	else
> +		ret = acpi_pci_probe_root_resources(info);
> +	if (ret < 0)
> +		goto out_release_info;
> +
> +	pci_acpi_root_add_resources(info);
> +	pci_add_resource(&info->resources, &root->secondary);
> +	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> +				  sysdata, &info->resources);

Thank a lot for this cleanup!!

I recall you already considered passing segment (domain nr) to 
pci_create_root_bus, right? Can you please remind me why we gave up on this?

I am asking because currently I can not find the way to retrieve domain 
number from pci_bus_assign_domain_nr (for those platforms which choose 
PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which is 
the part of pci_create_root_bus.

Regards,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21  9:57   ` Tomasz Nowicki
@ 2015-10-21 11:02     ` Liviu Dudau
  2015-10-21 11:27       ` Tomasz Nowicki
  0 siblings, 1 reply; 56+ messages in thread
From: Liviu Dudau @ 2015-10-21 11:02 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, linux-acpi, linux-pci, linux-kernel,
	x86

On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
> On 14.10.2015 08:29, 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.
> >
> >Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >Tested-by: Tony Luck <tony.luck@intel.com>
> >Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> >Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> >---
> >  drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/pci-acpi.h |   24 ++++++
> >  2 files changed, 228 insertions(+)
> >
> 
> [...]
> 
> >+
> >+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 *sysdata)
> >+{
> >+	int ret, busnum = root->secondary.start;
> >+	struct acpi_device *device = root->device;
> >+	int node = acpi_get_node(device->handle);
> >+	struct pci_bus *bus;
> >+
> >+	info->root = root;
> >+	info->bridge = device;
> >+	info->ops = ops;
> >+	INIT_LIST_HEAD(&info->resources);
> >+	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> >+		 root->segment, busnum);
> >+
> >+	if (ops->init_info && ops->init_info(info))
> >+		goto out_release_info;
> >+	if (ops->prepare_resources)
> >+		ret = ops->prepare_resources(info);
> >+	else
> >+		ret = acpi_pci_probe_root_resources(info);
> >+	if (ret < 0)
> >+		goto out_release_info;
> >+
> >+	pci_acpi_root_add_resources(info);
> >+	pci_add_resource(&info->resources, &root->secondary);
> >+	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> >+				  sysdata, &info->resources);
> 
> Thank a lot for this cleanup!!
> 
> I recall you already considered passing segment (domain nr) to
> pci_create_root_bus, right? Can you please remind me why we gave up on this?
> 
> I am asking because currently I can not find the way to retrieve domain
> number from pci_bus_assign_domain_nr (for those platforms which choose
> PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which is the
> part of pci_create_root_bus.

Not sure I fully understand your question, but pci_bus_assign_domain_nr() will
put the assigned domain number in bus->domain_nr if you chose PCI_DOMAINS_GENERIC.
Do you want to override that value with the segment nr from MCFG?

Best regards,
Liviu

> 
> Regards,
> Tomasz
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21 11:02     ` Liviu Dudau
@ 2015-10-21 11:27       ` Tomasz Nowicki
  2015-10-21 11:42         ` Lorenzo Pieralisi
                           ` (2 more replies)
  0 siblings, 3 replies; 56+ messages in thread
From: Tomasz Nowicki @ 2015-10-21 11:27 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, linux-acpi, linux-pci, linux-kernel,
	x86

On 21.10.2015 13:02, Liviu Dudau wrote:
> On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
>> On 14.10.2015 08:29, 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.
>>>
>>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>>> Tested-by: Tony Luck <tony.luck@intel.com>
>>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>>> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
>>> ---
>>>   drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
>>>   include/linux/pci-acpi.h |   24 ++++++
>>>   2 files changed, 228 insertions(+)
>>>
>>
>> [...]
>>
>>> +
>>> +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 *sysdata)
>>> +{
>>> +	int ret, busnum = root->secondary.start;
>>> +	struct acpi_device *device = root->device;
>>> +	int node = acpi_get_node(device->handle);
>>> +	struct pci_bus *bus;
>>> +
>>> +	info->root = root;
>>> +	info->bridge = device;
>>> +	info->ops = ops;
>>> +	INIT_LIST_HEAD(&info->resources);
>>> +	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
>>> +		 root->segment, busnum);
>>> +
>>> +	if (ops->init_info && ops->init_info(info))
>>> +		goto out_release_info;
>>> +	if (ops->prepare_resources)
>>> +		ret = ops->prepare_resources(info);
>>> +	else
>>> +		ret = acpi_pci_probe_root_resources(info);
>>> +	if (ret < 0)
>>> +		goto out_release_info;
>>> +
>>> +	pci_acpi_root_add_resources(info);
>>> +	pci_add_resource(&info->resources, &root->secondary);
>>> +	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
>>> +				  sysdata, &info->resources);
>>
>> Thank a lot for this cleanup!!
>>
>> I recall you already considered passing segment (domain nr) to
>> pci_create_root_bus, right? Can you please remind me why we gave up on this?
>>
>> I am asking because currently I can not find the way to retrieve domain
>> number from pci_bus_assign_domain_nr (for those platforms which choose
>> PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which is the
>> part of pci_create_root_bus.
>
> Not sure I fully understand your question, but pci_bus_assign_domain_nr() will
> put the assigned domain number in bus->domain_nr if you chose PCI_DOMAINS_GENERIC.
> Do you want to override that value with the segment nr from MCFG?
>

Let me give ACPI ARM64 example:

1. We parse MCFG table and get segment nr assigned to root bridge
2. Then PCI host bridge calls acpi_pci_root_create -> 
pci_create_root_bus -> pci_bus_assign_domain_nr
3. At this point we cannot get segment nr for ACPI

So I would like to assign MCFG segment nr to bus->domain_nr being in 
pci_bus_assign_domain_nr giving we have scenario above.

Thanks,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21 11:27       ` Tomasz Nowicki
@ 2015-10-21 11:42         ` Lorenzo Pieralisi
  2015-10-21 12:16           ` Tomasz Nowicki
  2015-10-21 11:48         ` Liviu Dudau
  2015-10-21 11:49         ` Jiang Liu
  2 siblings, 1 reply; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-10-21 11:42 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Liviu Dudau, Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, linux-acpi, linux-pci, linux-kernel,
	x86

On Wed, Oct 21, 2015 at 01:27:33PM +0200, Tomasz Nowicki wrote:
> On 21.10.2015 13:02, Liviu Dudau wrote:
> >On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
> >>On 14.10.2015 08:29, 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.
> >>>
> >>>Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >>>Tested-by: Tony Luck <tony.luck@intel.com>
> >>>Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> >>>Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> >>>---
> >>>  drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
> >>>  include/linux/pci-acpi.h |   24 ++++++
> >>>  2 files changed, 228 insertions(+)
> >>>
> >>
> >>[...]
> >>
> >>>+
> >>>+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 *sysdata)
> >>>+{
> >>>+	int ret, busnum = root->secondary.start;
> >>>+	struct acpi_device *device = root->device;
> >>>+	int node = acpi_get_node(device->handle);
> >>>+	struct pci_bus *bus;
> >>>+
> >>>+	info->root = root;
> >>>+	info->bridge = device;
> >>>+	info->ops = ops;
> >>>+	INIT_LIST_HEAD(&info->resources);
> >>>+	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> >>>+		 root->segment, busnum);
> >>>+
> >>>+	if (ops->init_info && ops->init_info(info))
> >>>+		goto out_release_info;
> >>>+	if (ops->prepare_resources)
> >>>+		ret = ops->prepare_resources(info);
> >>>+	else
> >>>+		ret = acpi_pci_probe_root_resources(info);
> >>>+	if (ret < 0)
> >>>+		goto out_release_info;
> >>>+
> >>>+	pci_acpi_root_add_resources(info);
> >>>+	pci_add_resource(&info->resources, &root->secondary);
> >>>+	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> >>>+				  sysdata, &info->resources);
> >>
> >>Thank a lot for this cleanup!!
> >>
> >>I recall you already considered passing segment (domain nr) to
> >>pci_create_root_bus, right? Can you please remind me why we gave up on this?
> >>
> >>I am asking because currently I can not find the way to retrieve domain
> >>number from pci_bus_assign_domain_nr (for those platforms which choose
> >>PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which is the
> >>part of pci_create_root_bus.
> >
> >Not sure I fully understand your question, but pci_bus_assign_domain_nr() will
> >put the assigned domain number in bus->domain_nr if you chose PCI_DOMAINS_GENERIC.
> >Do you want to override that value with the segment nr from MCFG?
> >
> 
> Let me give ACPI ARM64 example:
> 
> 1. We parse MCFG table and get segment nr assigned to root bridge
> 2. Then PCI host bridge calls acpi_pci_root_create ->
> pci_create_root_bus -> pci_bus_assign_domain_nr
> 3. At this point we cannot get segment nr for ACPI
> 
> So I would like to assign MCFG segment nr to bus->domain_nr being in
> pci_bus_assign_domain_nr giving we have scenario above.

I do not understand what you mean by "assign MCFG segment" here, please
explain. The MCFG segment group number is used to look-up the configuration
space for a given host bridge, not to assign a domain number to it.

The domain_nr above is the value returned by the _SEG object for the host
bridge device.

Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21 11:27       ` Tomasz Nowicki
  2015-10-21 11:42         ` Lorenzo Pieralisi
@ 2015-10-21 11:48         ` Liviu Dudau
  2015-10-21 11:49         ` Jiang Liu
  2 siblings, 0 replies; 56+ messages in thread
From: Liviu Dudau @ 2015-10-21 11:48 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, linux-acpi, linux-pci, linux-kernel,
	x86

On Wed, Oct 21, 2015 at 01:27:33PM +0200, Tomasz Nowicki wrote:
> On 21.10.2015 13:02, Liviu Dudau wrote:
> >On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
> >>On 14.10.2015 08:29, 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.
> >>>
> >>>Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >>>Tested-by: Tony Luck <tony.luck@intel.com>
> >>>Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> >>>Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> >>>---
> >>>  drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
> >>>  include/linux/pci-acpi.h |   24 ++++++
> >>>  2 files changed, 228 insertions(+)
> >>>
> >>
> >>[...]
> >>
> >>>+
> >>>+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 *sysdata)
> >>>+{
> >>>+	int ret, busnum = root->secondary.start;
> >>>+	struct acpi_device *device = root->device;
> >>>+	int node = acpi_get_node(device->handle);
> >>>+	struct pci_bus *bus;
> >>>+
> >>>+	info->root = root;
> >>>+	info->bridge = device;
> >>>+	info->ops = ops;
> >>>+	INIT_LIST_HEAD(&info->resources);
> >>>+	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> >>>+		 root->segment, busnum);
> >>>+
> >>>+	if (ops->init_info && ops->init_info(info))
> >>>+		goto out_release_info;
> >>>+	if (ops->prepare_resources)
> >>>+		ret = ops->prepare_resources(info);
> >>>+	else
> >>>+		ret = acpi_pci_probe_root_resources(info);
> >>>+	if (ret < 0)
> >>>+		goto out_release_info;
> >>>+
> >>>+	pci_acpi_root_add_resources(info);
> >>>+	pci_add_resource(&info->resources, &root->secondary);
> >>>+	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> >>>+				  sysdata, &info->resources);
> >>
> >>Thank a lot for this cleanup!!
> >>
> >>I recall you already considered passing segment (domain nr) to
> >>pci_create_root_bus, right? Can you please remind me why we gave up on this?
> >>
> >>I am asking because currently I can not find the way to retrieve domain
> >>number from pci_bus_assign_domain_nr (for those platforms which choose
> >>PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which is the
> >>part of pci_create_root_bus.
> >
> >Not sure I fully understand your question, but pci_bus_assign_domain_nr() will
> >put the assigned domain number in bus->domain_nr if you chose PCI_DOMAINS_GENERIC.
> >Do you want to override that value with the segment nr from MCFG?
> >
> 
> Let me give ACPI ARM64 example:
> 
> 1. We parse MCFG table and get segment nr assigned to root bridge
> 2. Then PCI host bridge calls acpi_pci_root_create -> pci_create_root_bus ->
> pci_bus_assign_domain_nr
> 3. At this point we cannot get segment nr for ACPI
> 
> So I would like to assign MCFG segment nr to bus->domain_nr being in
> pci_bus_assign_domain_nr giving we have scenario above.

I thought so. What about adding code to pci_bus_assign_domain_nr() to get the
segment nr from MCFG table? I know the function looks scary and the comments
don't seem to acknowledge that use_dt_domain static variable has actually 3
possible values (-1, 0, 1) but you can use -1 to mean "try ACPI segment nr
first" (just a suggestion, you or others might have a better idea).

Best regards,
Liviu

> 
> Thanks,
> Tomasz
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21 11:27       ` Tomasz Nowicki
  2015-10-21 11:42         ` Lorenzo Pieralisi
  2015-10-21 11:48         ` Liviu Dudau
@ 2015-10-21 11:49         ` Jiang Liu
  2015-10-21 11:52             ` Liviu Dudau
  2 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-10-21 11:49 UTC (permalink / raw)
  To: Tomasz Nowicki, Liviu Dudau
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, linux-acpi, linux-pci, linux-kernel,
	x86

On 2015/10/21 19:27, Tomasz Nowicki wrote:
> On 21.10.2015 13:02, Liviu Dudau wrote:
>> On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
>>> On 14.10.2015 08:29, 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.
>>>>
>>>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>>>> Tested-by: Tony Luck <tony.luck@intel.com>
>>>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>>>> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
>>>> ---
>>>>   drivers/acpi/pci_root.c  |  204
>>>> ++++++++++++++++++++++++++++++++++++++++++++++
>>>>   include/linux/pci-acpi.h |   24 ++++++
>>>>   2 files changed, 228 insertions(+)
>>>>
>>>
>>> [...]
>>>
>>>> +
>>>> +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 *sysdata)
>>>> +{
>>>> +    int ret, busnum = root->secondary.start;
>>>> +    struct acpi_device *device = root->device;
>>>> +    int node = acpi_get_node(device->handle);
>>>> +    struct pci_bus *bus;
>>>> +
>>>> +    info->root = root;
>>>> +    info->bridge = device;
>>>> +    info->ops = ops;
>>>> +    INIT_LIST_HEAD(&info->resources);
>>>> +    snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
>>>> +         root->segment, busnum);
>>>> +
>>>> +    if (ops->init_info && ops->init_info(info))
>>>> +        goto out_release_info;
>>>> +    if (ops->prepare_resources)
>>>> +        ret = ops->prepare_resources(info);
>>>> +    else
>>>> +        ret = acpi_pci_probe_root_resources(info);
>>>> +    if (ret < 0)
>>>> +        goto out_release_info;
>>>> +
>>>> +    pci_acpi_root_add_resources(info);
>>>> +    pci_add_resource(&info->resources, &root->secondary);
>>>> +    bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
>>>> +                  sysdata, &info->resources);
>>>
>>> Thank a lot for this cleanup!!
>>>
>>> I recall you already considered passing segment (domain nr) to
>>> pci_create_root_bus, right? Can you please remind me why we gave up
>>> on this?
>>>
>>> I am asking because currently I can not find the way to retrieve domain
>>> number from pci_bus_assign_domain_nr (for those platforms which choose
>>> PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which
>>> is the
>>> part of pci_create_root_bus.
>>
>> Not sure I fully understand your question, but
>> pci_bus_assign_domain_nr() will
>> put the assigned domain number in bus->domain_nr if you chose
>> PCI_DOMAINS_GENERIC.
>> Do you want to override that value with the segment nr from MCFG?
>>
> 
> Let me give ACPI ARM64 example:
> 
> 1. We parse MCFG table and get segment nr assigned to root bridge
> 2. Then PCI host bridge calls acpi_pci_root_create ->
> pci_create_root_bus -> pci_bus_assign_domain_nr
> 3. At this point we cannot get segment nr for ACPI
> 
> So I would like to assign MCFG segment nr to bus->domain_nr being in
> pci_bus_assign_domain_nr giving we have scenario above.
Please use sysdata for that, IA64 and x86 are making use of sysdata
to store such information:
struct pci_sysdata {
        int             domain;         /* PCI domain */
        int             node;           /* NUMA node */
#ifdef CONFIG_ACPI
        struct acpi_device *companion;  /* ACPI companion device */
#endif
#ifdef CONFIG_X86_64
        void            *iommu;         /* IOMMU private data */
#endif
};

Hanjun once tried to introduce struct pci_sysdata for ARM64, but
seems it has been rejected.

> 
> Thanks,
> Tomasz
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21 11:49         ` Jiang Liu
@ 2015-10-21 11:52             ` Liviu Dudau
  0 siblings, 0 replies; 56+ messages in thread
From: Liviu Dudau @ 2015-10-21 11:52 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki,
	Lorenzo Pieralisi, Marc Zyngier, Hanjun Guo, linux-acpi,
	linux-pci, linux-kernel, x86

On Wed, Oct 21, 2015 at 07:49:13PM +0800, Jiang Liu wrote:
> On 2015/10/21 19:27, Tomasz Nowicki wrote:
> > On 21.10.2015 13:02, Liviu Dudau wrote:
> >> On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
> >>> On 14.10.2015 08:29, 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.
> >>>>
> >>>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >>>> Tested-by: Tony Luck <tony.luck@intel.com>
> >>>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> >>>> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> >>>> ---
> >>>>   drivers/acpi/pci_root.c  |  204
> >>>> ++++++++++++++++++++++++++++++++++++++++++++++
> >>>>   include/linux/pci-acpi.h |   24 ++++++
> >>>>   2 files changed, 228 insertions(+)
> >>>>
> >>>
> >>> [...]
> >>>
> >>>> +
> >>>> +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 *sysdata)
> >>>> +{
> >>>> +    int ret, busnum = root->secondary.start;
> >>>> +    struct acpi_device *device = root->device;
> >>>> +    int node = acpi_get_node(device->handle);
> >>>> +    struct pci_bus *bus;
> >>>> +
> >>>> +    info->root = root;
> >>>> +    info->bridge = device;
> >>>> +    info->ops = ops;
> >>>> +    INIT_LIST_HEAD(&info->resources);
> >>>> +    snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> >>>> +         root->segment, busnum);
> >>>> +
> >>>> +    if (ops->init_info && ops->init_info(info))
> >>>> +        goto out_release_info;
> >>>> +    if (ops->prepare_resources)
> >>>> +        ret = ops->prepare_resources(info);
> >>>> +    else
> >>>> +        ret = acpi_pci_probe_root_resources(info);
> >>>> +    if (ret < 0)
> >>>> +        goto out_release_info;
> >>>> +
> >>>> +    pci_acpi_root_add_resources(info);
> >>>> +    pci_add_resource(&info->resources, &root->secondary);
> >>>> +    bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> >>>> +                  sysdata, &info->resources);
> >>>
> >>> Thank a lot for this cleanup!!
> >>>
> >>> I recall you already considered passing segment (domain nr) to
> >>> pci_create_root_bus, right? Can you please remind me why we gave up
> >>> on this?
> >>>
> >>> I am asking because currently I can not find the way to retrieve domain
> >>> number from pci_bus_assign_domain_nr (for those platforms which choose
> >>> PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which
> >>> is the
> >>> part of pci_create_root_bus.
> >>
> >> Not sure I fully understand your question, but
> >> pci_bus_assign_domain_nr() will
> >> put the assigned domain number in bus->domain_nr if you chose
> >> PCI_DOMAINS_GENERIC.
> >> Do you want to override that value with the segment nr from MCFG?
> >>
> > 
> > Let me give ACPI ARM64 example:
> > 
> > 1. We parse MCFG table and get segment nr assigned to root bridge
> > 2. Then PCI host bridge calls acpi_pci_root_create ->
> > pci_create_root_bus -> pci_bus_assign_domain_nr
> > 3. At this point we cannot get segment nr for ACPI
> > 
> > So I would like to assign MCFG segment nr to bus->domain_nr being in
> > pci_bus_assign_domain_nr giving we have scenario above.
> Please use sysdata for that, IA64 and x86 are making use of sysdata
> to store such information:
> struct pci_sysdata {
>         int             domain;         /* PCI domain */
>         int             node;           /* NUMA node */
> #ifdef CONFIG_ACPI
>         struct acpi_device *companion;  /* ACPI companion device */
> #endif
> #ifdef CONFIG_X86_64
>         void            *iommu;         /* IOMMU private data */
> #endif
> };
> 
> Hanjun once tried to introduce struct pci_sysdata for ARM64, but
> seems it has been rejected.

For good reason! There is a lot of duplication between different arches notion
of the pci_sysdata and they can be moved into pci_bus or pci_host_bridge
structures. The goal is to get rid of multiple pci_sysdata structures, not
to add more.

Best regards,
Liviu

> 
> > 
> > Thanks,
> > Tomasz
> > -- 
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
@ 2015-10-21 11:52             ` Liviu Dudau
  0 siblings, 0 replies; 56+ messages in thread
From: Liviu Dudau @ 2015-10-21 11:52 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki,
	Lorenzo Pieralisi, Marc Zyngier, Hanjun Guo, linux-acpi,
	linux-pci, linux-kernel, x86

On Wed, Oct 21, 2015 at 07:49:13PM +0800, Jiang Liu wrote:
> On 2015/10/21 19:27, Tomasz Nowicki wrote:
> > On 21.10.2015 13:02, Liviu Dudau wrote:
> >> On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
> >>> On 14.10.2015 08:29, 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.
> >>>>
> >>>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> >>>> Tested-by: Tony Luck <tony.luck@intel.com>
> >>>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> >>>> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> >>>> ---
> >>>>   drivers/acpi/pci_root.c  |  204
> >>>> ++++++++++++++++++++++++++++++++++++++++++++++
> >>>>   include/linux/pci-acpi.h |   24 ++++++
> >>>>   2 files changed, 228 insertions(+)
> >>>>
> >>>
> >>> [...]
> >>>
> >>>> +
> >>>> +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 *sysdata)
> >>>> +{
> >>>> +    int ret, busnum = root->secondary.start;
> >>>> +    struct acpi_device *device = root->device;
> >>>> +    int node = acpi_get_node(device->handle);
> >>>> +    struct pci_bus *bus;
> >>>> +
> >>>> +    info->root = root;
> >>>> +    info->bridge = device;
> >>>> +    info->ops = ops;
> >>>> +    INIT_LIST_HEAD(&info->resources);
> >>>> +    snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
> >>>> +         root->segment, busnum);
> >>>> +
> >>>> +    if (ops->init_info && ops->init_info(info))
> >>>> +        goto out_release_info;
> >>>> +    if (ops->prepare_resources)
> >>>> +        ret = ops->prepare_resources(info);
> >>>> +    else
> >>>> +        ret = acpi_pci_probe_root_resources(info);
> >>>> +    if (ret < 0)
> >>>> +        goto out_release_info;
> >>>> +
> >>>> +    pci_acpi_root_add_resources(info);
> >>>> +    pci_add_resource(&info->resources, &root->secondary);
> >>>> +    bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> >>>> +                  sysdata, &info->resources);
> >>>
> >>> Thank a lot for this cleanup!!
> >>>
> >>> I recall you already considered passing segment (domain nr) to
> >>> pci_create_root_bus, right? Can you please remind me why we gave up
> >>> on this?
> >>>
> >>> I am asking because currently I can not find the way to retrieve domain
> >>> number from pci_bus_assign_domain_nr (for those platforms which choose
> >>> PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which
> >>> is the
> >>> part of pci_create_root_bus.
> >>
> >> Not sure I fully understand your question, but
> >> pci_bus_assign_domain_nr() will
> >> put the assigned domain number in bus->domain_nr if you chose
> >> PCI_DOMAINS_GENERIC.
> >> Do you want to override that value with the segment nr from MCFG?
> >>
> > 
> > Let me give ACPI ARM64 example:
> > 
> > 1. We parse MCFG table and get segment nr assigned to root bridge
> > 2. Then PCI host bridge calls acpi_pci_root_create ->
> > pci_create_root_bus -> pci_bus_assign_domain_nr
> > 3. At this point we cannot get segment nr for ACPI
> > 
> > So I would like to assign MCFG segment nr to bus->domain_nr being in
> > pci_bus_assign_domain_nr giving we have scenario above.
> Please use sysdata for that, IA64 and x86 are making use of sysdata
> to store such information:
> struct pci_sysdata {
>         int             domain;         /* PCI domain */
>         int             node;           /* NUMA node */
> #ifdef CONFIG_ACPI
>         struct acpi_device *companion;  /* ACPI companion device */
> #endif
> #ifdef CONFIG_X86_64
>         void            *iommu;         /* IOMMU private data */
> #endif
> };
> 
> Hanjun once tried to introduce struct pci_sysdata for ARM64, but
> seems it has been rejected.

For good reason! There is a lot of duplication between different arches notion
of the pci_sysdata and they can be moved into pci_bus or pci_host_bridge
structures. The goal is to get rid of multiple pci_sysdata structures, not
to add more.

Best regards,
Liviu

> 
> > 
> > Thanks,
> > Tomasz
> > -- 
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-21 11:42         ` Lorenzo Pieralisi
@ 2015-10-21 12:16           ` Tomasz Nowicki
  0 siblings, 0 replies; 56+ messages in thread
From: Tomasz Nowicki @ 2015-10-21 12:16 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Liviu Dudau, Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, linux-acpi, linux-pci, linux-kernel,
	x86

On 21.10.2015 13:42, Lorenzo Pieralisi wrote:
> On Wed, Oct 21, 2015 at 01:27:33PM +0200, Tomasz Nowicki wrote:
>> On 21.10.2015 13:02, Liviu Dudau wrote:
>>> On Wed, Oct 21, 2015 at 11:57:53AM +0200, Tomasz Nowicki wrote:
>>>> On 14.10.2015 08:29, 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.
>>>>>
>>>>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>>>>> Tested-by: Tony Luck <tony.luck@intel.com>
>>>>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>>>>> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
>>>>> ---
>>>>>   drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>   include/linux/pci-acpi.h |   24 ++++++
>>>>>   2 files changed, 228 insertions(+)
>>>>>
>>>>
>>>> [...]
>>>>
>>>>> +
>>>>> +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 *sysdata)
>>>>> +{
>>>>> +	int ret, busnum = root->secondary.start;
>>>>> +	struct acpi_device *device = root->device;
>>>>> +	int node = acpi_get_node(device->handle);
>>>>> +	struct pci_bus *bus;
>>>>> +
>>>>> +	info->root = root;
>>>>> +	info->bridge = device;
>>>>> +	info->ops = ops;
>>>>> +	INIT_LIST_HEAD(&info->resources);
>>>>> +	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
>>>>> +		 root->segment, busnum);
>>>>> +
>>>>> +	if (ops->init_info && ops->init_info(info))
>>>>> +		goto out_release_info;
>>>>> +	if (ops->prepare_resources)
>>>>> +		ret = ops->prepare_resources(info);
>>>>> +	else
>>>>> +		ret = acpi_pci_probe_root_resources(info);
>>>>> +	if (ret < 0)
>>>>> +		goto out_release_info;
>>>>> +
>>>>> +	pci_acpi_root_add_resources(info);
>>>>> +	pci_add_resource(&info->resources, &root->secondary);
>>>>> +	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
>>>>> +				  sysdata, &info->resources);
>>>>
>>>> Thank a lot for this cleanup!!
>>>>
>>>> I recall you already considered passing segment (domain nr) to
>>>> pci_create_root_bus, right? Can you please remind me why we gave up on this?
>>>>
>>>> I am asking because currently I can not find the way to retrieve domain
>>>> number from pci_bus_assign_domain_nr (for those platforms which choose
>>>> PCI_DOMAINS_GENERIC and want to use segment nr from MCFG table) which is the
>>>> part of pci_create_root_bus.
>>>
>>> Not sure I fully understand your question, but pci_bus_assign_domain_nr() will
>>> put the assigned domain number in bus->domain_nr if you chose PCI_DOMAINS_GENERIC.
>>> Do you want to override that value with the segment nr from MCFG?
>>>
>>
>> Let me give ACPI ARM64 example:
>>
>> 1. We parse MCFG table and get segment nr assigned to root bridge
>> 2. Then PCI host bridge calls acpi_pci_root_create ->
>> pci_create_root_bus -> pci_bus_assign_domain_nr
>> 3. At this point we cannot get segment nr for ACPI
>>
>> So I would like to assign MCFG segment nr to bus->domain_nr being in
>> pci_bus_assign_domain_nr giving we have scenario above.
>
> I do not understand what you mean by "assign MCFG segment" here, please
> explain. The MCFG segment group number is used to look-up the configuration
> space for a given host bridge, not to assign a domain number to it.
>
> The domain_nr above is the value returned by the _SEG object for the host
> bridge device.

If I read the code correctly, MCFG region assigned to PCI host bridge X 
should have the same value for its segment field and corresponding _SEG 
object. Anyway, you are right, the MCFG segment group number should be 
used to look-up the configuration space and _SEG object to retrieve 
domain nr.

To evaluate _SEG object being in pci_bus_assign_domain_nr we still miss 
there the PCI host bridge device. So I should change my previous 
question, can we pass down the PCI host bridge device to be able to call 
_SEG object being in pci_bus_assign_domain_nr?

Thanks,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-10-14  6:29 ` [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create() Jiang Liu
  2015-10-15 20:47   ` Bjorn Helgaas
  2015-10-21  9:57   ` Tomasz Nowicki
@ 2015-11-05 14:21   ` Tomasz Nowicki
  2015-11-05 18:19     ` Lorenzo Pieralisi
  2015-11-06  7:51     ` Jiang Liu
  2 siblings, 2 replies; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-05 14:21 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 14.10.2015 08:29, 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.
>
> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Tested-by: Tony Luck <tony.luck@intel.com>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
> ---
>   drivers/acpi/pci_root.c  |  204 ++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/pci-acpi.h |   24 ++++++
>   2 files changed, 228 insertions(+)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 393706a5261b..850d7bf0c873 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -652,6 +652,210 @@ static void acpi_pci_root_remove(struct acpi_device *device)
>   	kfree(root);
>   }
>
> +/*
> + * Following code to support acpi_pci_root_create() is copied from
> + * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
> + * and ARM64.
> + */
> +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);
> +	}
> +}
> +
> +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);

It is not clear to me why we need these two calls above ^^^. We are 
using pci_acpi_root_add_resources(info) later. Is it not enough?

Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI 
driver. It is because acpi_dev_get_resources is adding 
translation_offset to IO ranges start address and then:
acpi_pci_root_validate_resources(&device->dev, list,
				 IORESOURCE_IO);
rejects that IO regions as it is out of my 0x0-SZ_16M window.

Does acpi_pci_probe_root_resources meant to be x86 specific and I should 
avoid using it?

Thanks,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-05 14:21   ` Tomasz Nowicki
@ 2015-11-05 18:19     ` Lorenzo Pieralisi
  2015-11-06  7:55       ` Jiang Liu
                         ` (2 more replies)
  2015-11-06  7:51     ` Jiang Liu
  1 sibling, 3 replies; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-05 18:19 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
> On 14.10.2015 08:29, Jiang Liu wrote:

[...]

> >+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);
> >+	}
> >+}
> >+
> >+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);
> 
> It is not clear to me why we need these two calls above ^^^. We are
> using pci_acpi_root_add_resources(info) later. Is it not enough?
> 
> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
> driver. It is because acpi_dev_get_resources is adding
> translation_offset to IO ranges start address and then:
> acpi_pci_root_validate_resources(&device->dev, list,
> 				 IORESOURCE_IO);
> rejects that IO regions as it is out of my 0x0-SZ_16M window.
> 
> Does acpi_pci_probe_root_resources meant to be x86 specific and I
> should avoid using it?

IIUC, you _have_ to have the proper translation_offset to map the bridge
window into the IO address space:

http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html

Then, using the offset, you should do something ia64 does, namely,
retrieve the CPU address corresponding to IO space (see arch/ia64/pci/pci.c
- add_io_space()) and map it in the physical address space by using
pci_remap_iospace(), it is similar to what we have to do with DT.

It is extremely confusing and I am not sure I got it right myself,
I am still grokking ia64 code to understand what it really does.

So basically, the IO bridge window coming from acpi_dev_get_resource()
should represent the IO space in 0 - 16M, IIUC.

By using the offset (that was initialized using translation_offset) and
the resource->start, you can retrieve the cpu address that you need to
actually map the IO space, since that's what we do on ARM (ie the
IO resource is an offset into the virtual address space set aside
for IO).

Confusing, to say the least. Jiang, did I get it right ?

Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-05 14:21   ` Tomasz Nowicki
  2015-11-05 18:19     ` Lorenzo Pieralisi
@ 2015-11-06  7:51     ` Jiang Liu
  1 sibling, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-11-06  7:51 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 2015/11/5 22:21, Tomasz Nowicki wrote:
> On 14.10.2015 08:29, 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.
>>
>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Tested-by: Tony Luck <tony.luck@intel.com>
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
>> ---
>>   drivers/acpi/pci_root.c  |  204
>> ++++++++++++++++++++++++++++++++++++++++++++++
>>   include/linux/pci-acpi.h |   24 ++++++
>>   2 files changed, 228 insertions(+)
>>
>> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
>> index 393706a5261b..850d7bf0c873 100644
>> --- a/drivers/acpi/pci_root.c
>> +++ b/drivers/acpi/pci_root.c
>> @@ -652,6 +652,210 @@ static void acpi_pci_root_remove(struct
>> acpi_device *device)
>>       kfree(root);
>>   }
>>
>> +/*
>> + * Following code to support acpi_pci_root_create() is copied from
>> + * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
>> + * and ARM64.
>> + */
>> +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);
>> +    }
>> +}
>> +
>> +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);
> 
> It is not clear to me why we need these two calls above ^^^. We are
> using pci_acpi_root_add_resources(info) later. Is it not enough?
Hi Tomasz,
	acpi_pci_root_validate_resources() will try adjust (or fix)
conflicting resources among all resources of the PCI host bridge,
but pci_acpi_root_add_resources() only rejects conflicting resources.

> 
> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
> driver. It is because acpi_dev_get_resources is adding
> translation_offset to IO ranges start address and then:
> acpi_pci_root_validate_resources(&device->dev, list,
>                  IORESOURCE_IO);
> rejects that IO regions as it is out of my 0x0-SZ_16M window.
> 
> Does acpi_pci_probe_root_resources meant to be x86 specific and I should
> avoid using it?
It should be generic, but we have some issue in support of
translation_offset. I'm trying to get this fixed.
Thanks,
Gerry

> 
> Thanks,
> Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-05 18:19     ` Lorenzo Pieralisi
@ 2015-11-06  7:55       ` Jiang Liu
  2015-11-06  8:52       ` Jiang Liu
  2015-11-06 10:18       ` Tomasz Nowicki
  2 siblings, 0 replies; 56+ messages in thread
From: Jiang Liu @ 2015-11-06  7:55 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Tomasz Nowicki
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier, Hanjun Guo,
	Liviu Dudau, linux-acpi, linux-pci, linux-kernel, x86

On 2015/11/6 2:19, Lorenzo Pieralisi wrote:
> On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
>> On 14.10.2015 08:29, Jiang Liu wrote:
> 
> [...]
> 
>>> +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);
>>> +	}
>>> +}
>>> +
>>> +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);
>>
>> It is not clear to me why we need these two calls above ^^^. We are
>> using pci_acpi_root_add_resources(info) later. Is it not enough?
>>
>> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
>> driver. It is because acpi_dev_get_resources is adding
>> translation_offset to IO ranges start address and then:
>> acpi_pci_root_validate_resources(&device->dev, list,
>> 				 IORESOURCE_IO);
>> rejects that IO regions as it is out of my 0x0-SZ_16M window.
>>
>> Does acpi_pci_probe_root_resources meant to be x86 specific and I
>> should avoid using it?
> 
> IIUC, you _have_ to have the proper translation_offset to map the bridge
> window into the IO address space:
> 
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
> 
> Then, using the offset, you should do something ia64 does, namely,
> retrieve the CPU address corresponding to IO space (see arch/ia64/pci/pci.c
> - add_io_space()) and map it in the physical address space by using
> pci_remap_iospace(), it is similar to what we have to do with DT.
> 
> It is extremely confusing and I am not sure I got it right myself,
> I am still grokking ia64 code to understand what it really does.
> 
> So basically, the IO bridge window coming from acpi_dev_get_resource()
> should represent the IO space in 0 - 16M, IIUC.
> 
> By using the offset (that was initialized using translation_offset) and
> the resource->start, you can retrieve the cpu address that you need to
> actually map the IO space, since that's what we do on ARM (ie the
> IO resource is an offset into the virtual address space set aside
> for IO).
> 
> Confusing, to say the least. Jiang, did I get it right ?
Yes, you are right, but seems I have done something wrong here.
Currently res->start = acpi_des->start + acpi_des->translation_offset,
which seems wrong. I will try to check IA64 side again and find
a fix for this.

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-05 18:19     ` Lorenzo Pieralisi
  2015-11-06  7:55       ` Jiang Liu
@ 2015-11-06  8:52       ` Jiang Liu
  2015-11-06 10:37         ` Tomasz Nowicki
  2015-11-06 12:51         ` Lorenzo Pieralisi
  2015-11-06 10:18       ` Tomasz Nowicki
  2 siblings, 2 replies; 56+ messages in thread
From: Jiang Liu @ 2015-11-06  8:52 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Tomasz Nowicki
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier, Hanjun Guo,
	Liviu Dudau, linux-acpi, linux-pci, linux-kernel, x86

On 2015/11/6 2:19, Lorenzo Pieralisi wrote:
> On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
>> On 14.10.2015 08:29, Jiang Liu wrote:
> 
> [...]
> 
>>> +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);
>>> +	}
>>> +}
>>> +
>>> +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);
>>
>> It is not clear to me why we need these two calls above ^^^. We are
>> using pci_acpi_root_add_resources(info) later. Is it not enough?
>>
>> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
>> driver. It is because acpi_dev_get_resources is adding
>> translation_offset to IO ranges start address and then:
>> acpi_pci_root_validate_resources(&device->dev, list,
>> 				 IORESOURCE_IO);
>> rejects that IO regions as it is out of my 0x0-SZ_16M window.
>>
>> Does acpi_pci_probe_root_resources meant to be x86 specific and I
>> should avoid using it?
> 
> IIUC, you _have_ to have the proper translation_offset to map the bridge
> window into the IO address space:
> 
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
> 
> Then, using the offset, you should do something ia64 does, namely,
> retrieve the CPU address corresponding to IO space (see arch/ia64/pci/pci.c
> - add_io_space()) and map it in the physical address space by using
> pci_remap_iospace(), it is similar to what we have to do with DT.
> 
> It is extremely confusing and I am not sure I got it right myself,
> I am still grokking ia64 code to understand what it really does.
> 
> So basically, the IO bridge window coming from acpi_dev_get_resource()
> should represent the IO space in 0 - 16M, IIUC.
> 
> By using the offset (that was initialized using translation_offset) and
> the resource->start, you can retrieve the cpu address that you need to
> actually map the IO space, since that's what we do on ARM (ie the
> IO resource is an offset into the virtual address space set aside
> for IO).
> 
> Confusing, to say the least. Jiang, did I get it right ?
Hi Lorenzo and Tomasz,
	With a cup of coffee, I got myself awake eventually:)
Now we are going to talk about IO port on IA64, really a little
complex:( Actually there are two types of translation.
1) A PCI domain has a 24-bit IO port address space, there may
be multiple IO port address spaces in systems with multiple PCI
domains. So the first type of translation is to translate domain
specific IO port address into system global IO port address
(iomem_resource) by
  res->start = acpi_des->start + acpi_des->translation_offset

2) IA64 needs to map IO port address spaces into MMIO address
space because it has no instructions to access IO ports directly.
So IA64 has reserved a MMIO range to map IO port address spaces.
This type of translation relies on architecture specific information
instead of ACPI descriptors.

On the other hand, ACPI specification has defined  "I/O to Memory
Translation" flag and "Memory to I/O Translation" flag in
ACPI Extended Address Space Descriptor, but current implementation
doesn't really support such a use case. So we need to find a way
out here. Could you please help to provide more information about
PCI host bridge resource descriptor implementation details on
ARM64?

> 
> Lorenzo
> 

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-05 18:19     ` Lorenzo Pieralisi
  2015-11-06  7:55       ` Jiang Liu
  2015-11-06  8:52       ` Jiang Liu
@ 2015-11-06 10:18       ` Tomasz Nowicki
  2 siblings, 0 replies; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-06 10:18 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 05.11.2015 19:19, Lorenzo Pieralisi wrote:
> On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
>> On 14.10.2015 08:29, Jiang Liu wrote:
>
> [...]
>
>>> +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);
>>> +	}
>>> +}
>>> +
>>> +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);
>>
>> It is not clear to me why we need these two calls above ^^^. We are
>> using pci_acpi_root_add_resources(info) later. Is it not enough?
>>
>> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
>> driver. It is because acpi_dev_get_resources is adding
>> translation_offset to IO ranges start address and then:
>> acpi_pci_root_validate_resources(&device->dev, list,
>> 				 IORESOURCE_IO);
>> rejects that IO regions as it is out of my 0x0-SZ_16M window.
>>
>> Does acpi_pci_probe_root_resources meant to be x86 specific and I
>> should avoid using it?
>
> IIUC, you _have_ to have the proper translation_offset to map the bridge
> window into the IO address space:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
>
> Then, using the offset, you should do something ia64 does, namely,
> retrieve the CPU address corresponding to IO space (see arch/ia64/pci/pci.c
> - add_io_space()) and map it in the physical address space by using
> pci_remap_iospace(), it is similar to what we have to do with DT.
>
> It is extremely confusing and I am not sure I got it right myself,
> I am still grokking ia64 code to understand what it really does.
>
> So basically, the IO bridge window coming from acpi_dev_get_resource()
> should represent the IO space in 0 - 16M, IIUC.

Yes, you are right IMO.

>
> By using the offset (that was initialized using translation_offset) and
> the resource->start, you can retrieve the cpu address that you need to
> actually map the IO space, since that's what we do on ARM (ie the
> IO resource is an offset into the virtual address space set aside
> for IO).
>

Right, that is clear to me, below my current implementation example 
which works for ARM64 now:

static struct acpi_pci_root_ops acpi_pci_root_ops = {
[...]
	.prepare_resources = pci_acpi_root_prepare_resources,
};

static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
{
	struct list_head *list = &ci->resources;
	struct acpi_device *device = ci->bridge;
	struct resource_entry *entry, *tmp;
	unsigned long flags;
	int ret;

	flags = IORESOURCE_IO | IORESOURCE_MEM;
	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);
		return ret;
	} else if (ret == 0)
		dev_dbg(&device->dev,
			"no IO and memory resources present in _CRS\n");

	resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
		struct resource *res = entry->res;

		if (entry->res->flags & IORESOURCE_DISABLED)
			resource_list_destroy_entry(entry);
		else
			res->name = ci->name;

		/*
		 * TODO: need to move pci_register_io_range() function out
		 * of drivers/of/address.c for both used by DT and ACPI
		 */
		if (res->flags & IORESOURCE_IO) {
			unsigned long port;
			int err;
			resource_size_t length = res->end - res->start;
			resource_size_t start = res->start;

			err = pci_register_io_range(res->start, length);
			if (err) {
				resource_list_destroy_entry(entry);
				continue;
			}

			port = pci_address_to_pio(res->start);
			if (port == (unsigned long)-1) {
				resource_list_destroy_entry(entry);
				continue;
			}

			res->start = port;
			res->end = res->start + length;
			entry->offset = port - (start - entry->offset);

			if (pci_remap_iospace(res, start) < 0)
				resource_list_destroy_entry(entry);
		}
	}
	return ret;
}

As you see acpi_dev_get_resources returns:
res->start = acpi_des->start + acpi_des->translation_offset (CPU address)
which then must be adjusted as you described to get io port and call 
pci_remap_iospace.

This is also why I can not use acpi_pci_probe_root_resources here. Lets 
assume we have IO range like that DSDT table form QEMU:
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
          0x00000000,         // Granularity
          0x00000000,         // Range Minimum
          0x0000FFFF,         // Range Maximum
          0x3EFF0000,         // Translation Offset
          0x00010000,         // Length
          ,, , TypeStatic)
so see acpi_dev_get_resources returns res->start = acpi_des->start (0x0) 
+ acpi_des->translation_offset(0x3EFF0000) = 0x3EFF0000. This will be 
rejected in acpi_pci_root_validate_resources() as 0x3EFF0000 does not 
fit within 0-16M.

My question is if acpi_pci_probe_root_resources is handling 
translation_offset properly and if we have some silent assumption 
specific for e.g. ia64 here.

Thanks for help in looking at it.

Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06  8:52       ` Jiang Liu
@ 2015-11-06 10:37         ` Tomasz Nowicki
  2015-11-06 11:46           ` Jiang Liu
  2015-11-06 12:51         ` Lorenzo Pieralisi
  1 sibling, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-06 10:37 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 06.11.2015 09:52, Jiang Liu wrote:
> On 2015/11/6 2:19, Lorenzo Pieralisi wrote:
>> On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
>>> On 14.10.2015 08:29, Jiang Liu wrote:
>>
>> [...]
>>
>>>> +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);
>>>> +	}
>>>> +}
>>>> +
>>>> +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);
>>>
>>> It is not clear to me why we need these two calls above ^^^. We are
>>> using pci_acpi_root_add_resources(info) later. Is it not enough?
>>>
>>> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
>>> driver. It is because acpi_dev_get_resources is adding
>>> translation_offset to IO ranges start address and then:
>>> acpi_pci_root_validate_resources(&device->dev, list,
>>> 				 IORESOURCE_IO);
>>> rejects that IO regions as it is out of my 0x0-SZ_16M window.
>>>
>>> Does acpi_pci_probe_root_resources meant to be x86 specific and I
>>> should avoid using it?
>>
>> IIUC, you _have_ to have the proper translation_offset to map the bridge
>> window into the IO address space:
>>
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
>>
>> Then, using the offset, you should do something ia64 does, namely,
>> retrieve the CPU address corresponding to IO space (see arch/ia64/pci/pci.c
>> - add_io_space()) and map it in the physical address space by using
>> pci_remap_iospace(), it is similar to what we have to do with DT.
>>
>> It is extremely confusing and I am not sure I got it right myself,
>> I am still grokking ia64 code to understand what it really does.
>>
>> So basically, the IO bridge window coming from acpi_dev_get_resource()
>> should represent the IO space in 0 - 16M, IIUC.
>>
>> By using the offset (that was initialized using translation_offset) and
>> the resource->start, you can retrieve the cpu address that you need to
>> actually map the IO space, since that's what we do on ARM (ie the
>> IO resource is an offset into the virtual address space set aside
>> for IO).
>>
>> Confusing, to say the least. Jiang, did I get it right ?
> Hi Lorenzo and Tomasz,
> 	With a cup of coffee, I got myself awake eventually:)
> Now we are going to talk about IO port on IA64, really a little
> complex:( Actually there are two types of translation.
> 1) A PCI domain has a 24-bit IO port address space, there may
> be multiple IO port address spaces in systems with multiple PCI
> domains. So the first type of translation is to translate domain
> specific IO port address into system global IO port address
> (iomem_resource) by
>    res->start = acpi_des->start + acpi_des->translation_offset
>
> 2) IA64 needs to map IO port address spaces into MMIO address
> space because it has no instructions to access IO ports directly.
> So IA64 has reserved a MMIO range to map IO port address spaces.
> This type of translation relies on architecture specific information
> instead of ACPI descriptors.
>
> On the other hand, ACPI specification has defined  "I/O to Memory
> Translation" flag and "Memory to I/O Translation" flag in
> ACPI Extended Address Space Descriptor,

Based on 2) and above, does it mean IA64 should use "ACPI Extended 
Address Space Descriptor" for its PCI bridge IO windows only?

  but current implementation
> doesn't really support such a use case. So we need to find a way
> out here. Could you please help to provide more information about
> PCI host bridge resource descriptor implementation details on
> ARM64?
>

Sure, ARM64 (0-16M IO space) QEMU example:
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
          0x00000000,         // Granularity
          0x00000000,         // Range Minimum
          0x0000FFFF,         // Range Maximum
          0x3EFF0000,         // Translation Offset
          0x00010000,         // Length
          ,, , TypeStatic)

You can also have a look at my implementation example in mail to Lorenzo.

Thanks,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 10:37         ` Tomasz Nowicki
@ 2015-11-06 11:46           ` Jiang Liu
  2015-11-06 12:40             ` Tomasz Nowicki
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-06 11:46 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 2015/11/6 18:37, Tomasz Nowicki wrote:
> On 06.11.2015 09:52, Jiang Liu wrote:
>> On 2015/11/6 2:19, Lorenzo Pieralisi wrote:
>>> On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
>>>> On 14.10.2015 08:29, Jiang Liu wrote:
>>>
>>> [...]
>>>
>>>>> +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);
>>>>> +    }
>>>>> +}
>>>>> +
>>>>> +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);
>>>>
>>>> It is not clear to me why we need these two calls above ^^^. We are
>>>> using pci_acpi_root_add_resources(info) later. Is it not enough?
>>>>
>>>> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
>>>> driver. It is because acpi_dev_get_resources is adding
>>>> translation_offset to IO ranges start address and then:
>>>> acpi_pci_root_validate_resources(&device->dev, list,
>>>>                  IORESOURCE_IO);
>>>> rejects that IO regions as it is out of my 0x0-SZ_16M window.
>>>>
>>>> Does acpi_pci_probe_root_resources meant to be x86 specific and I
>>>> should avoid using it?
>>>
>>> IIUC, you _have_ to have the proper translation_offset to map the bridge
>>> window into the IO address space:
>>>
>>> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
>>>
>>>
>>> Then, using the offset, you should do something ia64 does, namely,
>>> retrieve the CPU address corresponding to IO space (see
>>> arch/ia64/pci/pci.c
>>> - add_io_space()) and map it in the physical address space by using
>>> pci_remap_iospace(), it is similar to what we have to do with DT.
>>>
>>> It is extremely confusing and I am not sure I got it right myself,
>>> I am still grokking ia64 code to understand what it really does.
>>>
>>> So basically, the IO bridge window coming from acpi_dev_get_resource()
>>> should represent the IO space in 0 - 16M, IIUC.
>>>
>>> By using the offset (that was initialized using translation_offset) and
>>> the resource->start, you can retrieve the cpu address that you need to
>>> actually map the IO space, since that's what we do on ARM (ie the
>>> IO resource is an offset into the virtual address space set aside
>>> for IO).
>>>
>>> Confusing, to say the least. Jiang, did I get it right ?
>> Hi Lorenzo and Tomasz,
>>     With a cup of coffee, I got myself awake eventually:)
>> Now we are going to talk about IO port on IA64, really a little
>> complex:( Actually there are two types of translation.
>> 1) A PCI domain has a 24-bit IO port address space, there may
>> be multiple IO port address spaces in systems with multiple PCI
>> domains. So the first type of translation is to translate domain
>> specific IO port address into system global IO port address
>> (iomem_resource) by
>>    res->start = acpi_des->start + acpi_des->translation_offset
>>
>> 2) IA64 needs to map IO port address spaces into MMIO address
>> space because it has no instructions to access IO ports directly.
>> So IA64 has reserved a MMIO range to map IO port address spaces.
>> This type of translation relies on architecture specific information
>> instead of ACPI descriptors.
>>
>> On the other hand, ACPI specification has defined  "I/O to Memory
>> Translation" flag and "Memory to I/O Translation" flag in
>> ACPI Extended Address Space Descriptor,
> 
> Based on 2) and above, does it mean IA64 should use "ACPI Extended
> Address Space Descriptor" for its PCI bridge IO windows only?
> 
>  but current implementation
>> doesn't really support such a use case. So we need to find a way
>> out here. Could you please help to provide more information about
>> PCI host bridge resource descriptor implementation details on
>> ARM64?
>>
> 
> Sure, ARM64 (0-16M IO space) QEMU example:
> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>          0x00000000,         // Granularity
>          0x00000000,         // Range Minimum
>          0x0000FFFF,         // Range Maximum
>          0x3EFF0000,         // Translation Offset
>          0x00010000,         // Length
>          ,, , TypeStatic)
The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
According to my understanding, ARM/ARM64 has no concept of IO port
address space, so the PCI host bridge will map IO port on PCI side
onto MMIO on host side. In other words, PCI host bridge on ARM64
implement a IO Port->MMIO translation instead of a IO Port->IO Port
translation. If that's true, it should use 'TypeTranslation' instead
of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
support 'TypeTranslation' yet, so we need to find a solution for it.
Thanks,
Gerry

> 
> You can also have a look at my implementation example in mail to Lorenzo.
> 
> Thanks,
> Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 11:46           ` Jiang Liu
@ 2015-11-06 12:40             ` Tomasz Nowicki
  2015-11-06 13:22               ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-06 12:40 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 06.11.2015 12:46, Jiang Liu wrote:
> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>> On 06.11.2015 09:52, Jiang Liu wrote:
>>> On 2015/11/6 2:19, Lorenzo Pieralisi wrote:
>>>> On Thu, Nov 05, 2015 at 03:21:34PM +0100, Tomasz Nowicki wrote:
>>>>> On 14.10.2015 08:29, Jiang Liu wrote:
>>>>
>>>> [...]
>>>>
>>>>>> +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);
>>>>>> +    }
>>>>>> +}
>>>>>> +
>>>>>> +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);
>>>>>
>>>>> It is not clear to me why we need these two calls above ^^^. We are
>>>>> using pci_acpi_root_add_resources(info) later. Is it not enough?
>>>>>
>>>>> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
>>>>> driver. It is because acpi_dev_get_resources is adding
>>>>> translation_offset to IO ranges start address and then:
>>>>> acpi_pci_root_validate_resources(&device->dev, list,
>>>>>                   IORESOURCE_IO);
>>>>> rejects that IO regions as it is out of my 0x0-SZ_16M window.
>>>>>
>>>>> Does acpi_pci_probe_root_resources meant to be x86 specific and I
>>>>> should avoid using it?
>>>>
>>>> IIUC, you _have_ to have the proper translation_offset to map the bridge
>>>> window into the IO address space:
>>>>
>>>> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
>>>>
>>>>
>>>> Then, using the offset, you should do something ia64 does, namely,
>>>> retrieve the CPU address corresponding to IO space (see
>>>> arch/ia64/pci/pci.c
>>>> - add_io_space()) and map it in the physical address space by using
>>>> pci_remap_iospace(), it is similar to what we have to do with DT.
>>>>
>>>> It is extremely confusing and I am not sure I got it right myself,
>>>> I am still grokking ia64 code to understand what it really does.
>>>>
>>>> So basically, the IO bridge window coming from acpi_dev_get_resource()
>>>> should represent the IO space in 0 - 16M, IIUC.
>>>>
>>>> By using the offset (that was initialized using translation_offset) and
>>>> the resource->start, you can retrieve the cpu address that you need to
>>>> actually map the IO space, since that's what we do on ARM (ie the
>>>> IO resource is an offset into the virtual address space set aside
>>>> for IO).
>>>>
>>>> Confusing, to say the least. Jiang, did I get it right ?
>>> Hi Lorenzo and Tomasz,
>>>      With a cup of coffee, I got myself awake eventually:)
>>> Now we are going to talk about IO port on IA64, really a little
>>> complex:( Actually there are two types of translation.
>>> 1) A PCI domain has a 24-bit IO port address space, there may
>>> be multiple IO port address spaces in systems with multiple PCI
>>> domains. So the first type of translation is to translate domain
>>> specific IO port address into system global IO port address
>>> (iomem_resource) by
>>>     res->start = acpi_des->start + acpi_des->translation_offset
>>>
>>> 2) IA64 needs to map IO port address spaces into MMIO address
>>> space because it has no instructions to access IO ports directly.
>>> So IA64 has reserved a MMIO range to map IO port address spaces.
>>> This type of translation relies on architecture specific information
>>> instead of ACPI descriptors.
>>>
>>> On the other hand, ACPI specification has defined  "I/O to Memory
>>> Translation" flag and "Memory to I/O Translation" flag in
>>> ACPI Extended Address Space Descriptor,
>>
>> Based on 2) and above, does it mean IA64 should use "ACPI Extended
>> Address Space Descriptor" for its PCI bridge IO windows only?
>>
>>   but current implementation
>>> doesn't really support such a use case. So we need to find a way
>>> out here. Could you please help to provide more information about
>>> PCI host bridge resource descriptor implementation details on
>>> ARM64?
>>>
>>
>> Sure, ARM64 (0-16M IO space) QEMU example:
>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>           0x00000000,         // Granularity
>>           0x00000000,         // Range Minimum
>>           0x0000FFFF,         // Range Maximum
>>           0x3EFF0000,         // Translation Offset
>>           0x00010000,         // Length
>>           ,, , TypeStatic)
> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
> According to my understanding, ARM/ARM64 has no concept of IO port
> address space, so the PCI host bridge will map IO port on PCI side
> onto MMIO on host side. In other words, PCI host bridge on ARM64
> implement a IO Port->MMIO translation instead of a IO Port->IO Port
> translation. If that's true, it should use 'TypeTranslation' instead
> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
> support 'TypeTranslation' yet, so we need to find a solution for it.

I think you are right, we need TypeTranslation flag for ARM64 DWordIO 
descriptors and an extra kernel patch to support it.

Thanks,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06  8:52       ` Jiang Liu
  2015-11-06 10:37         ` Tomasz Nowicki
@ 2015-11-06 12:51         ` Lorenzo Pieralisi
  1 sibling, 0 replies; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-06 12:51 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On Fri, Nov 06, 2015 at 04:52:47PM +0800, Jiang Liu wrote:

[...]

> >>> +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);
> >>
> >> It is not clear to me why we need these two calls above ^^^. We are
> >> using pci_acpi_root_add_resources(info) later. Is it not enough?
> >>
> >> Also, I cannot use acpi_pci_probe_root_resources() in my ARM64 PCI
> >> driver. It is because acpi_dev_get_resources is adding
> >> translation_offset to IO ranges start address and then:
> >> acpi_pci_root_validate_resources(&device->dev, list,
> >> 				 IORESOURCE_IO);
> >> rejects that IO regions as it is out of my 0x0-SZ_16M window.
> >>
> >> Does acpi_pci_probe_root_resources meant to be x86 specific and I
> >> should avoid using it?
> > 
> > IIUC, you _have_ to have the proper translation_offset to map the bridge
> > window into the IO address space:
> > 
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2015-June/348708.html
> > 
> > Then, using the offset, you should do something ia64 does, namely,
> > retrieve the CPU address corresponding to IO space (see arch/ia64/pci/pci.c
> > - add_io_space()) and map it in the physical address space by using
> > pci_remap_iospace(), it is similar to what we have to do with DT.
> > 
> > It is extremely confusing and I am not sure I got it right myself,
> > I am still grokking ia64 code to understand what it really does.
> > 
> > So basically, the IO bridge window coming from acpi_dev_get_resource()
> > should represent the IO space in 0 - 16M, IIUC.
> > 
> > By using the offset (that was initialized using translation_offset) and
> > the resource->start, you can retrieve the cpu address that you need to
> > actually map the IO space, since that's what we do on ARM (ie the
> > IO resource is an offset into the virtual address space set aside
> > for IO).
> > 
> > Confusing, to say the least. Jiang, did I get it right ?
> Hi Lorenzo and Tomasz,
> 	With a cup of coffee, I got myself awake eventually:)
> Now we are going to talk about IO port on IA64, really a little
> complex:( Actually there are two types of translation.
> 1) A PCI domain has a 24-bit IO port address space, there may
> be multiple IO port address spaces in systems with multiple PCI
> domains. So the first type of translation is to translate domain
> specific IO port address into system global IO port address
> (iomem_resource) by
>   res->start = acpi_des->start + acpi_des->translation_offset

And that's what I do not understand, or better I do not understand
why the acpi_pci_root_validate_resources (for IO) does not fail on ia64,
since that should work as arm64, namely IO ports are mapped through
MMIO.

I think the check in acpi_pci_root_validate_resources() (for
IORESOURCE_IO) fails at present on ia64 too, correct ?

If not, how can it work ? res->start definitely contains the
CPU physical address mapping IO space after adding the
translation_offset, so the check in acpi_pci_root_validate_resources()
for IO can't succeed.

In add_io_space() ia64 does the same thing as Tomasz has to do,
namely overwriting the res->start and end with the offset into
the virtual address space allocated for IO, which is different from
the CPU physical address allocated to IO space.

Please correct me if I am wrong.

> 2) IA64 needs to map IO port address spaces into MMIO address
> space because it has no instructions to access IO ports directly.
> So IA64 has reserved a MMIO range to map IO port address spaces.
> This type of translation relies on architecture specific information
> instead of ACPI descriptors.

That's how ARM64 works too, the IO space resources are an offset into
a chunk of virtual address space allocated to PCI IO memory, so it
seems to me that arm64 and ia64 should work the same way, and that
at present acpi_pci_root_validate_resources() should fail on ia64 too.

Thanks,
Lorenzo

> 
> On the other hand, ACPI specification has defined  "I/O to Memory
> Translation" flag and "Memory to I/O Translation" flag in
> ACPI Extended Address Space Descriptor, but current implementation
> doesn't really support such a use case. So we need to find a way
> out here. Could you please help to provide more information about
> PCI host bridge resource descriptor implementation details on
> ARM64?
> 
> > 
> > Lorenzo
> > 
> 

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 12:40             ` Tomasz Nowicki
@ 2015-11-06 13:22               ` Jiang Liu
  2015-11-06 14:45                 ` Lorenzo Pieralisi
  2015-11-09 14:07                 ` Tomasz Nowicki
  0 siblings, 2 replies; 56+ messages in thread
From: Jiang Liu @ 2015-11-06 13:22 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Lorenzo Pieralisi, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

[-- Attachment #1: Type: text/plain, Size: 1384 bytes --]

On 2015/11/6 20:40, Tomasz Nowicki wrote:
> On 06.11.2015 12:46, Jiang Liu wrote:
>> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>>> On 06.11.2015 09:52, Jiang Liu wrote:
>>> Sure, ARM64 (0-16M IO space) QEMU example:
>>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>>           0x00000000,         // Granularity
>>>           0x00000000,         // Range Minimum
>>>           0x0000FFFF,         // Range Maximum
>>>           0x3EFF0000,         // Translation Offset
>>>           0x00010000,         // Length
>>>           ,, , TypeStatic)
>> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
>> According to my understanding, ARM/ARM64 has no concept of IO port
>> address space, so the PCI host bridge will map IO port on PCI side
>> onto MMIO on host side. In other words, PCI host bridge on ARM64
>> implement a IO Port->MMIO translation instead of a IO Port->IO Port
>> translation. If that's true, it should use 'TypeTranslation' instead
>> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
>> support 'TypeTranslation' yet, so we need to find a solution for it.
> 
> I think you are right, we need TypeTranslation flag for ARM64 DWordIO
> descriptors and an extra kernel patch to support it.
How about the attached to patch to support TypeTranslation?
It only passes compilation:)

> 
> Thanks,
> Tomasz

[-- Attachment #2: 0001-.patch --]
[-- Type: text/x-patch, Size: 2231 bytes --]

>From 51f5cddd8c4301b731805074ebc3e3a6c7dbaf59 Mon Sep 17 00:00:00 2001
From: Liu Jiang <jiang.liu@linux.intel.com>
Date: Fri, 6 Nov 2015 20:01:59 +0800
Subject: [PATCH]


Signed-off-by: Liu Jiang <jiang.liu@linux.intel.com>
---
 drivers/acpi/resource.c      |   25 +++++++++++++++++++++++--
 include/linux/resource_ext.h |    7 +++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index cdc5c2599beb..1bd3e21f56fe 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -215,8 +215,29 @@ static bool acpi_decode_space(struct resource_win *win,
 	else if (attr->translation_offset)
 		pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
 			 attr->translation_offset);
-	start = attr->minimum + offset;
-	end = attr->maximum + offset;
+	start = attr->minimum;
+	end = attr->maximum;
+
+	/*
+	 * Convert bus local address into system global address if it's an
+	 * IO Port->IO Port or MMIO->MMIO translation.
+	 */
+	switch (addr->resource_type) {
+	case ACPI_MEMORY_RANGE:
+		if (addr->info.mem.translation)
+			win->translation_type = RESOURCE_TRANS_MMIO_TO_IOPORT;
+		else
+			start += offset;
+		break;
+	case ACPI_IO_RANGE:
+		if (addr->info.io.translation)
+			win->translation_type = RESOURCE_TRANS_IOPORT_TO_MMIO;
+		else
+			start += offset;
+		break;
+	default:
+		break;
+	}
 
 	win->offset = offset;
 	res->start = start;
diff --git a/include/linux/resource_ext.h b/include/linux/resource_ext.h
index e2bf63d881d4..f06d358c1f22 100644
--- a/include/linux/resource_ext.h
+++ b/include/linux/resource_ext.h
@@ -22,8 +22,15 @@
 struct resource_win {
 	struct resource res;		/* In master (CPU) address space */
 	resource_size_t offset;		/* Translation offset for bridge */
+	int translation_type;		/* Translation type for bridge */
 };
 
+#define RESOURCE_TRANS_SAME		0x0
+/* Translate from IO port on slave into MMIO on master */
+#define RESOURCE_TRANS_IOPORT_TO_MMIO	0x1
+/* Translate from MMIO on slave into IO port on master */
+#define RESOURCE_TRANS_MMIO_TO_IOPORT	0x2
+
 /*
  * Common resource list management data structure and interfaces to support
  * ACPI, PNP and PCI host bridge etc.
-- 
1.7.10.4


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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 13:22               ` Jiang Liu
@ 2015-11-06 14:45                 ` Lorenzo Pieralisi
  2015-11-06 15:32                   ` Jiang Liu
  2015-11-09 14:07                 ` Tomasz Nowicki
  1 sibling, 1 reply; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-06 14:45 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On Fri, Nov 06, 2015 at 09:22:46PM +0800, Jiang Liu wrote:
> On 2015/11/6 20:40, Tomasz Nowicki wrote:
> > On 06.11.2015 12:46, Jiang Liu wrote:
> >> On 2015/11/6 18:37, Tomasz Nowicki wrote:
> >>> On 06.11.2015 09:52, Jiang Liu wrote:
> >>> Sure, ARM64 (0-16M IO space) QEMU example:
> >>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> >>>           0x00000000,         // Granularity
> >>>           0x00000000,         // Range Minimum
> >>>           0x0000FFFF,         // Range Maximum
> >>>           0x3EFF0000,         // Translation Offset
> >>>           0x00010000,         // Length
> >>>           ,, , TypeStatic)
> >> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
> >> According to my understanding, ARM/ARM64 has no concept of IO port
> >> address space, so the PCI host bridge will map IO port on PCI side
> >> onto MMIO on host side. In other words, PCI host bridge on ARM64
> >> implement a IO Port->MMIO translation instead of a IO Port->IO Port
> >> translation. If that's true, it should use 'TypeTranslation' instead
> >> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
> >> support 'TypeTranslation' yet, so we need to find a solution for it.
> > 
> > I think you are right, we need TypeTranslation flag for ARM64 DWordIO
> > descriptors and an extra kernel patch to support it.
> How about the attached to patch to support TypeTranslation?
> It only passes compilation:)

Eh, hopefully there are not any ACPI tables out there with that bit
set that work _today_ and would not work with the patch attached :)

My question is still there: do we want to handle the same problem
as ia64 has in a different manner ? Certainly we won't be able
to update ia64 platforms ACPI tables, so we would end up with
two platforms handling IO resources in different ways unless I am
missing something here.

BTW, why would we add offset to res->start only if TypeTranslation is
clear ? Is not that something we would do just to make things "work" ?
That flag has no bearing on the offset, only on the resource type AFAIK.

This without taking into account ARM64 systems shipping with ACPI
tables that does not set the TypeTranslation at present.

On top of that, I noticed that core ACPI code handles Sparse
Translation (ie _TRS), that should be considered meaningful only if _TTP
is set (and that's not checked).

Thoughts ?

Thanks,
Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 14:45                 ` Lorenzo Pieralisi
@ 2015-11-06 15:32                   ` Jiang Liu
  2015-11-06 15:44                     ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-06 15:32 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 2015/11/6 22:45, Lorenzo Pieralisi wrote:
> On Fri, Nov 06, 2015 at 09:22:46PM +0800, Jiang Liu wrote:
>> On 2015/11/6 20:40, Tomasz Nowicki wrote:
>>> On 06.11.2015 12:46, Jiang Liu wrote:
>>>> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>>>>> On 06.11.2015 09:52, Jiang Liu wrote:
>>>>> Sure, ARM64 (0-16M IO space) QEMU example:
>>>>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>>>>           0x00000000,         // Granularity
>>>>>           0x00000000,         // Range Minimum
>>>>>           0x0000FFFF,         // Range Maximum
>>>>>           0x3EFF0000,         // Translation Offset
>>>>>           0x00010000,         // Length
>>>>>           ,, , TypeStatic)
>>>> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
>>>> According to my understanding, ARM/ARM64 has no concept of IO port
>>>> address space, so the PCI host bridge will map IO port on PCI side
>>>> onto MMIO on host side. In other words, PCI host bridge on ARM64
>>>> implement a IO Port->MMIO translation instead of a IO Port->IO Port
>>>> translation. If that's true, it should use 'TypeTranslation' instead
>>>> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
>>>> support 'TypeTranslation' yet, so we need to find a solution for it.
>>>
>>> I think you are right, we need TypeTranslation flag for ARM64 DWordIO
>>> descriptors and an extra kernel patch to support it.
>> How about the attached to patch to support TypeTranslation?
>> It only passes compilation:)
> 
> Eh, hopefully there are not any ACPI tables out there with that bit
> set that work _today_ and would not work with the patch attached :)
> 
> My question is still there: do we want to handle the same problem
> as ia64 has in a different manner ? Certainly we won't be able
> to update ia64 platforms ACPI tables, so we would end up with
> two platforms handling IO resources in different ways unless I am
> missing something here.
There are some difference between IA64 and ARM64.
On IA64, it supports 16M IO address space per PCI domain and 256 PCI
domains at max. So the system IO address space is 16M * 256 = 4G.
So it does two level translations to support IO port
1) translate PCI bus local IO port address into system global IO port
   address by adding acpi_des->translation_offset.
2) translate the 4G system IO port address space into MMIO address.
   IA64 has reserved a 4G space for IO port mapping. This translation
   is done by arch specific method.
In other word, IA64 needs two level translation, but ACPI only provides
on (trans_type, trans_offset) pair for encoding, so it's used for step 1).

For ARM64, I think currently it only needs step 2).

> 
> BTW, why would we add offset to res->start only if TypeTranslation is
> clear ? Is not that something we would do just to make things "work" ?
> That flag has no bearing on the offset, only on the resource type AFAIK.
It's not a hack, but a way to interpret ACPI spec:)

With current linux resource management framework, we need to allocate
both MMIO and IO port address space range for an ACPI resource of type
'TypeTranslation'. And struct resource could be either IO port or MMIO,
not both. So the choice is to keep the resource as IO port, and let
arch code to build the special MMIO mapping for it. Otherwise it will
break too many things if we convert the resource as MMIO.

That said, we need to add translation_offset to convert bus local
IO port address into system global IO port address if it's type of
TypeStatic, because ioresource_ioport uses system global IO port
address.

For an ACPI resource of type TypeTranslation, system global IO port
address equals bus local IO port address, and the translation_offset
is used to translate IO port address into MMIO address, so we shouldn't
add translation_offset to the IO port resource descriptor.

Thanks,
Gerry

> 
> This without taking into account ARM64 systems shipping with ACPI
> tables that does not set the TypeTranslation at present.
> 
> On top of that, I noticed that core ACPI code handles Sparse
> Translation (ie _TRS), that should be considered meaningful only if _TTP
> is set (and that's not checked).
Yes, that's a flaw:(

> 
> Thoughts ?
> 
> Thanks,
> Lorenzo
> 

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 15:32                   ` Jiang Liu
@ 2015-11-06 15:44                     ` Jiang Liu
  2015-11-23 15:23                       ` Sinan Kaya
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-06 15:44 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 2015/11/6 23:32, Jiang Liu wrote:
> On 2015/11/6 22:45, Lorenzo Pieralisi wrote:
>> On Fri, Nov 06, 2015 at 09:22:46PM +0800, Jiang Liu wrote:
>>> On 2015/11/6 20:40, Tomasz Nowicki wrote:
>>>> On 06.11.2015 12:46, Jiang Liu wrote:
>>>>> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>>>>>> On 06.11.2015 09:52, Jiang Liu wrote:
>>>>>> Sure, ARM64 (0-16M IO space) QEMU example:
>>>>>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>>>>>           0x00000000,         // Granularity
>>>>>>           0x00000000,         // Range Minimum
>>>>>>           0x0000FFFF,         // Range Maximum
>>>>>>           0x3EFF0000,         // Translation Offset
>>>>>>           0x00010000,         // Length
>>>>>>           ,, , TypeStatic)
>>>>> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
>>>>> According to my understanding, ARM/ARM64 has no concept of IO port
>>>>> address space, so the PCI host bridge will map IO port on PCI side
>>>>> onto MMIO on host side. In other words, PCI host bridge on ARM64
>>>>> implement a IO Port->MMIO translation instead of a IO Port->IO Port
>>>>> translation. If that's true, it should use 'TypeTranslation' instead
>>>>> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
>>>>> support 'TypeTranslation' yet, so we need to find a solution for it.
>>>>
>>>> I think you are right, we need TypeTranslation flag for ARM64 DWordIO
>>>> descriptors and an extra kernel patch to support it.
>>> How about the attached to patch to support TypeTranslation?
>>> It only passes compilation:)
>>
>> Eh, hopefully there are not any ACPI tables out there with that bit
>> set that work _today_ and would not work with the patch attached :)
>>
>> My question is still there: do we want to handle the same problem
>> as ia64 has in a different manner ? Certainly we won't be able
>> to update ia64 platforms ACPI tables, so we would end up with
>> two platforms handling IO resources in different ways unless I am
>> missing something here.
> There are some difference between IA64 and ARM64.
> On IA64, it supports 16M IO address space per PCI domain and 256 PCI
> domains at max. So the system IO address space is 16M * 256 = 4G.
> So it does two level translations to support IO port
> 1) translate PCI bus local IO port address into system global IO port
>    address by adding acpi_des->translation_offset.
> 2) translate the 4G system IO port address space into MMIO address.
>    IA64 has reserved a 4G space for IO port mapping. This translation
>    is done by arch specific method.
> In other word, IA64 needs two level translation, but ACPI only provides
> on (trans_type, trans_offset) pair for encoding, so it's used for step 1).
> 
> For ARM64, I think currently it only needs step 2).
> 
>>
>> BTW, why would we add offset to res->start only if TypeTranslation is
>> clear ? Is not that something we would do just to make things "work" ?
>> That flag has no bearing on the offset, only on the resource type AFAIK.
> It's not a hack, but a way to interpret ACPI spec:)
> 
> With current linux resource management framework, we need to allocate
> both MMIO and IO port address space range for an ACPI resource of type
> 'TypeTranslation'. And struct resource could be either IO port or MMIO,
> not both. So the choice is to keep the resource as IO port, and let
> arch code to build the special MMIO mapping for it. Otherwise it will
> break too many things if we convert the resource as MMIO.
> 
> That said, we need to add translation_offset to convert bus local
> IO port address into system global IO port address if it's type of
> TypeStatic, because ioresource_ioport uses system global IO port
> address.
> 
> For an ACPI resource of type TypeTranslation, system global IO port
> address equals bus local IO port address, and the translation_offset
> is used to translate IO port address into MMIO address, so we shouldn't
> add translation_offset to the IO port resource descriptor.
One note for the TypeTranslation case, the arch code needs to reset
resource_win->offset to zero after setting up the MMIO map. Sample
code as below:
va = ioremap(resource_win->offset + res->start, resource_size(res));
resource_win->offset = 0;

Otherwise it will break pcibios_resource_to_bus() etc.

> 
> Thanks,
> Gerry
> 
>>
>> This without taking into account ARM64 systems shipping with ACPI
>> tables that does not set the TypeTranslation at present.
>>
>> On top of that, I noticed that core ACPI code handles Sparse
>> Translation (ie _TRS), that should be considered meaningful only if _TTP
>> is set (and that's not checked).
> Yes, that's a flaw:(
> 
>>
>> Thoughts ?
>>
>> Thanks,
>> Lorenzo
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 13:22               ` Jiang Liu
  2015-11-06 14:45                 ` Lorenzo Pieralisi
@ 2015-11-09 14:07                 ` Tomasz Nowicki
  2015-11-09 17:10                   ` Lorenzo Pieralisi
  1 sibling, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-09 14:07 UTC (permalink / raw)
  To: Jiang Liu, Lorenzo Pieralisi
  Cc: Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier, Hanjun Guo,
	Liviu Dudau, linux-acpi, linux-pci, linux-kernel, x86

On 06.11.2015 14:22, Jiang Liu wrote:
> On 2015/11/6 20:40, Tomasz Nowicki wrote:
>> On 06.11.2015 12:46, Jiang Liu wrote:
>>> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>>>> On 06.11.2015 09:52, Jiang Liu wrote:
>>>> Sure, ARM64 (0-16M IO space) QEMU example:
>>>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>>>            0x00000000,         // Granularity
>>>>            0x00000000,         // Range Minimum
>>>>            0x0000FFFF,         // Range Maximum
>>>>            0x3EFF0000,         // Translation Offset
>>>>            0x00010000,         // Length
>>>>            ,, , TypeStatic)
>>> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
>>> According to my understanding, ARM/ARM64 has no concept of IO port
>>> address space, so the PCI host bridge will map IO port on PCI side
>>> onto MMIO on host side. In other words, PCI host bridge on ARM64
>>> implement a IO Port->MMIO translation instead of a IO Port->IO Port
>>> translation. If that's true, it should use 'TypeTranslation' instead
>>> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
>>> support 'TypeTranslation' yet, so we need to find a solution for it.
>>
>> I think you are right, we need TypeTranslation flag for ARM64 DWordIO
>> descriptors and an extra kernel patch to support it.
> How about the attached to patch to support TypeTranslation?
> It only passes compilation:)

Based on the further discussion, your draft patch looks good to me. 
Lorenzo, do you agree?

Gerry, what would be the best way to approach with this, extra patch of 
your set? or keep it separately, might be part of my set.

Thanks,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-09 14:07                 ` Tomasz Nowicki
@ 2015-11-09 17:10                   ` Lorenzo Pieralisi
  2015-11-09 20:09                     ` Arnd Bergmann
  0 siblings, 1 reply; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-09 17:10 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86, arnd

[CC'ing Arnd]

On Mon, Nov 09, 2015 at 03:07:38PM +0100, Tomasz Nowicki wrote:
> On 06.11.2015 14:22, Jiang Liu wrote:
> >On 2015/11/6 20:40, Tomasz Nowicki wrote:
> >>On 06.11.2015 12:46, Jiang Liu wrote:
> >>>On 2015/11/6 18:37, Tomasz Nowicki wrote:
> >>>>On 06.11.2015 09:52, Jiang Liu wrote:
> >>>>Sure, ARM64 (0-16M IO space) QEMU example:
> >>>>DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> >>>>           0x00000000,         // Granularity
> >>>>           0x00000000,         // Range Minimum
> >>>>           0x0000FFFF,         // Range Maximum
> >>>>           0x3EFF0000,         // Translation Offset
> >>>>           0x00010000,         // Length
> >>>>           ,, , TypeStatic)
> >>>The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
> >>>According to my understanding, ARM/ARM64 has no concept of IO port
> >>>address space, so the PCI host bridge will map IO port on PCI side
> >>>onto MMIO on host side. In other words, PCI host bridge on ARM64
> >>>implement a IO Port->MMIO translation instead of a IO Port->IO Port
> >>>translation. If that's true, it should use 'TypeTranslation' instead
> >>>of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
> >>>support 'TypeTranslation' yet, so we need to find a solution for it.
> >>
> >>I think you are right, we need TypeTranslation flag for ARM64 DWordIO
> >>descriptors and an extra kernel patch to support it.
> >How about the attached to patch to support TypeTranslation?
> >It only passes compilation:)
> 
> Based on the further discussion, your draft patch looks good to me.
> Lorenzo, do you agree?

No, because I still do not understand the difference between ia64 and
arm64 (they both drive IO ports cycles through MMIO so the resource
descriptors content must be the same or better they must mean the same
thing). On top of that, this is something that was heavily debated for DT:

http://www.spinics.net/lists/arm-kernel/msg345633.html

and I would like to get Arnd and Bjorn opinion on this because we
should not "interpret" ACPI specifications, we should understand
what they are supposed to describe and write kernel code accordingly.

In particular, I would like to understand, for an eg DWordIO descriptor,
what Range Minimum, Range Maximum and Translation Offset represent,
they can't mean different things depending on the SW parsing them,
this totally defeats the purpose.

By the way, ia64 ioremaps the translation_offset (ie new_space()), so
basically that's the CPU physical address at which the PCI host bridge
map the IO space transactions), I do not think ia64 is any different from
arm64 in this respect, if it is please provide an HW description here from
the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
tables would help).

Thanks,
Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-09 17:10                   ` Lorenzo Pieralisi
@ 2015-11-09 20:09                     ` Arnd Bergmann
  2015-11-10  5:50                       ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Arnd Bergmann @ 2015-11-09 20:09 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Tomasz Nowicki, Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Monday 09 November 2015 17:10:43 Lorenzo Pieralisi wrote:
> On Mon, Nov 09, 2015 at 03:07:38PM +0100, Tomasz Nowicki wrote:
> > On 06.11.2015 14:22, Jiang Liu wrote:
> > >On 2015/11/6 20:40, Tomasz Nowicki wrote:
> > >>On 06.11.2015 12:46, Jiang Liu wrote:
> > >>>On 2015/11/6 18:37, Tomasz Nowicki wrote:
> > >>>>On 06.11.2015 09:52, Jiang Liu wrote:
> > >>>>Sure, ARM64 (0-16M IO space) QEMU example:
> > >>>>DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
> > >>>>           0x00000000,         // Granularity
> > >>>>           0x00000000,         // Range Minimum
> > >>>>           0x0000FFFF,         // Range Maximum
> > >>>>           0x3EFF0000,         // Translation Offset
> > >>>>           0x00010000,         // Length
> > >>>>           ,, , TypeStatic)
> > >>>The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
> > >>>According to my understanding, ARM/ARM64 has no concept of IO port
> > >>>address space, so the PCI host bridge will map IO port on PCI side
> > >>>onto MMIO on host side. In other words, PCI host bridge on ARM64
> > >>>implement a IO Port->MMIO translation instead of a IO Port->IO Port
> > >>>translation. If that's true, it should use 'TypeTranslation' instead
> > >>>of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
> > >>>support 'TypeTranslation' yet, so we need to find a solution for it.
> > >>
> > >>I think you are right, we need TypeTranslation flag for ARM64 DWordIO
> > >>descriptors and an extra kernel patch to support it.
> > >How about the attached to patch to support TypeTranslation?
> > >It only passes compilation:)
> > 
> > Based on the further discussion, your draft patch looks good to me.
> > Lorenzo, do you agree?
> 
> No, because I still do not understand the difference between ia64 and
> arm64 (they both drive IO ports cycles through MMIO so the resource
> descriptors content must be the same or better they must mean the same
> thing). On top of that, this is something that was heavily debated for DT:
> 
> http://www.spinics.net/lists/arm-kernel/msg345633.html
> 
> and I would like to get Arnd and Bjorn opinion on this because we
> should not "interpret" ACPI specifications, we should understand
> what they are supposed to describe and write kernel code accordingly.
> 
> In particular, I would like to understand, for an eg DWordIO descriptor,
> what Range Minimum, Range Maximum and Translation Offset represent,
> they can't mean different things depending on the SW parsing them,
> this totally defeats the purpose.

I have no clue about what those mean in ACPI though.

Generally speaking, each PCI domain is expected to have a (normally 64KB)
range of CPU addresses that gets translated into PCI I/O space the same
way that config space and memory space are handled.
This is true for almost every architecture except for x86, which uses
different CPU instructions for I/O space compared to the other spaces.

> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
> basically that's the CPU physical address at which the PCI host bridge
> map the IO space transactions), I do not think ia64 is any different from
> arm64 in this respect, if it is please provide an HW description here from
> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
> tables would help).

The main difference between ia64 and a lot of the other architectures (e.g.
sparc is different again) is that ia64 defines a logical address range
in terms of having a small number for each I/O space followed by the
offset within that space as a 'port number' and uses a mapping function
that is defined as

static inline void *__ia64_mk_io_addr (unsigned long port)
{
        struct io_space *space = &io_space[IO_SPACE_NR(port)];
        return (space->mmio_base | IO_SPACE_PORT(port););
}
static inline unsigned int inl(unsigned long port)
{
        return *__ia64_mk_io_addr(port);
}

Most architectures allow only one I/O port range and put it at a fixed
virtual address so that inl() simply becomes 

static inline u32 inl(unsigned long addr)
{
        return readl(PCI_IOBASE + addr);
}

which noticeably reduces code size.

On some architectures (powerpc, arm, arm64), we then get the same simplified
definition with a fixed virtual address, and use pci_ioremap_io() or
something like that to to map a physical address range into this virtual
address window at the correct io_offset;

	Arnd

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-09 20:09                     ` Arnd Bergmann
@ 2015-11-10  5:50                       ` Jiang Liu
  2015-11-11 17:46                         ` Lorenzo Pieralisi
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-10  5:50 UTC (permalink / raw)
  To: Arnd Bergmann, Lorenzo Pieralisi
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

[-- Attachment #1: Type: text/plain, Size: 4814 bytes --]

On 2015/11/10 4:09, Arnd Bergmann wrote:
> On Monday 09 November 2015 17:10:43 Lorenzo Pieralisi wrote:
>> On Mon, Nov 09, 2015 at 03:07:38PM +0100, Tomasz Nowicki wrote:
>>> On 06.11.2015 14:22, Jiang Liu wrote:
>>>> On 2015/11/6 20:40, Tomasz Nowicki wrote:
>>>>> On 06.11.2015 12:46, Jiang Liu wrote:
>>>>>> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>>>>>>> On 06.11.2015 09:52, Jiang Liu wrote:
>>>>>>> Sure, ARM64 (0-16M IO space) QEMU example:
>>>>>>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>>>>>>           0x00000000,         // Granularity
>>>>>>>           0x00000000,         // Range Minimum
>>>>>>>           0x0000FFFF,         // Range Maximum
>>>>>>>           0x3EFF0000,         // Translation Offset
>>>>>>>           0x00010000,         // Length
>>>>>>>           ,, , TypeStatic)
>>>>>> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
>>>>>> According to my understanding, ARM/ARM64 has no concept of IO port
>>>>>> address space, so the PCI host bridge will map IO port on PCI side
>>>>>> onto MMIO on host side. In other words, PCI host bridge on ARM64
>>>>>> implement a IO Port->MMIO translation instead of a IO Port->IO Port
>>>>>> translation. If that's true, it should use 'TypeTranslation' instead
>>>>>> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
>>>>>> support 'TypeTranslation' yet, so we need to find a solution for it.
>>>>>
>>>>> I think you are right, we need TypeTranslation flag for ARM64 DWordIO
>>>>> descriptors and an extra kernel patch to support it.
>>>> How about the attached to patch to support TypeTranslation?
>>>> It only passes compilation:)
>>>
>>> Based on the further discussion, your draft patch looks good to me.
>>> Lorenzo, do you agree?
>>
>> No, because I still do not understand the difference between ia64 and
>> arm64 (they both drive IO ports cycles through MMIO so the resource
>> descriptors content must be the same or better they must mean the same
>> thing). On top of that, this is something that was heavily debated for DT:
>>
>> http://www.spinics.net/lists/arm-kernel/msg345633.html
>>
>> and I would like to get Arnd and Bjorn opinion on this because we
>> should not "interpret" ACPI specifications, we should understand
>> what they are supposed to describe and write kernel code accordingly.
>>
>> In particular, I would like to understand, for an eg DWordIO descriptor,
>> what Range Minimum, Range Maximum and Translation Offset represent,
>> they can't mean different things depending on the SW parsing them,
>> this totally defeats the purpose.
> 
> I have no clue about what those mean in ACPI though.
> 
> Generally speaking, each PCI domain is expected to have a (normally 64KB)
> range of CPU addresses that gets translated into PCI I/O space the same
> way that config space and memory space are handled.
> This is true for almost every architecture except for x86, which uses
> different CPU instructions for I/O space compared to the other spaces.
> 
>> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
>> basically that's the CPU physical address at which the PCI host bridge
>> map the IO space transactions), I do not think ia64 is any different from
>> arm64 in this respect, if it is please provide an HW description here from
>> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
>> tables would help).
> 
> The main difference between ia64 and a lot of the other architectures (e.g.
> sparc is different again) is that ia64 defines a logical address range
> in terms of having a small number for each I/O space followed by the
> offset within that space as a 'port number' and uses a mapping function
> that is defined as
> 
> static inline void *__ia64_mk_io_addr (unsigned long port)
> {
>         struct io_space *space = &io_space[IO_SPACE_NR(port)];
>         return (space->mmio_base | IO_SPACE_PORT(port););
> }
> static inline unsigned int inl(unsigned long port)
> {
>         return *__ia64_mk_io_addr(port);
> }
> 
> Most architectures allow only one I/O port range and put it at a fixed
> virtual address so that inl() simply becomes 
> 
> static inline u32 inl(unsigned long addr)
> {
>         return readl(PCI_IOBASE + addr);
> }
> 
> which noticeably reduces code size.
> 
> On some architectures (powerpc, arm, arm64), we then get the same simplified
> definition with a fixed virtual address, and use pci_ioremap_io() or
> something like that to to map a physical address range into this virtual
> address window at the correct io_offset;
Hi all,
	Thanks for explanation, I found a way to make the ACPI resource
parsing interface arch neutral, it should help to address Lorenzo's
concern. Please refer to the attached patch. (It's still RFC, not tested
yet).
Thanks,
Gerry

[-- Attachment #2: 0001-ACPI-PCI-Refine-the-way-to-handle-translation_offset.patch~ --]
[-- Type: text/plain, Size: 5415 bytes --]

>From 6521d3c5303b1d9830eecede4c1b778deffe17b0 Mon Sep 17 00:00:00 2001
From: Liu Jiang <jiang.liu@linux.intel.com>
Date: Tue, 10 Nov 2015 10:59:11 +0800
Subject: [PATCH] ACPI, PCI: Refine the way to handle translation_offset for
 ACPI resources

Some architectures, such as IA64 and ARM64, have no instructions to
directly access PCI IO ports, so they map PCI IO ports into PCI MMIO
address space. Typically PCI host bridges on those architectures take
the responsibility to map (translate) PCI IO port transactions into
Memory-Mapped IO transactions. ACPI specification provides support
of such a usage case by using resource translation_offset.

But current ACPI resource parsing interface isn't neutral enough,
it still has some special logic for IA64. So refine the ACPI resource
parsing interface and IA64 code to neutrally handle translation_offset
by:
1) ACPI resource parsing interface doesn't do any translation, it just
   save the translation_offset to be used by arch code.
2) Arch code will do the mapping(translation) based on arch specific
   information. Typically it does:
2.a) Translate per PCI domain IO port address space into system global
   IO port address space.
2.b) Setup MMIO address mapping for IO ports.
void handle_io_resource(struct resource_entry *io_entry)
{
	struct resource *mmio_res;

	mmio_res = kzalloc(sizeof(*mmio_res), GFP_KERNEL);
	mmio_res->flags = IORESOURCE_MEM;
	mmio_res->start = io_entry->offset + io_entry->res->start;
	mmio_res->end = io_entry->offset + io_entry->res->end;
	insert_resource(&iomem_resource, mmio_res)

	base = map_to_system_ioport_address(entry);
	io_entry->offset = base;
	io_entry->res->start += base;
	io_entry->res->end += base;
}

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/ia64/pci/pci.c     |   26 ++++++++++++++++----------
 drivers/acpi/resource.c |   12 +++++-------
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 8f6ac2f8ae4c..ee84300797d8 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -154,7 +154,7 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 	struct resource_entry *iospace;
 	struct resource *resource, *res = entry->res;
 	char *name;
-	unsigned long base, min, max, base_port;
+	unsigned long base_mmio, base_port;
 	unsigned int sparse = 0, space_nr, len;
 
 	len = strlen(info->common.name) + 32;
@@ -172,12 +172,10 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 		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_mmio = __pa(io_space[space_nr].mmio_base);
 	base_port = IO_SPACE_BASE(space_nr);
 	snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->common.name,
-		 base_port + min, base_port + max);
+		 base_port + res->start, base_port + res->end);
 
 	/*
 	 * The SDM guarantees the legacy 0-64K space is sparse, but if the
@@ -190,19 +188,27 @@ static int add_io_space(struct device *dev, struct pci_root_info *info,
 	resource = iospace->res;
 	resource->name  = name;
 	resource->flags = IORESOURCE_MEM;
-	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
-	resource->end   = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
+	resource->start = base_mmio;
+	resource->end = base_mmio;
+	if (sparse) {
+		resource->start += IO_SPACE_SPARSE_ENCODING(res->start);
+		resource->end += IO_SPACE_SPARSE_ENCODING(res->end);
+	} else {
+		resource->start += res->start;
+		resource->end += res->end;
+	}
 	if (insert_resource(&iomem_resource, resource)) {
 		dev_err(dev,
 			"can't allocate host bridge io space resource  %pR\n",
 			resource);
 		goto free_resource;
 	}
+	resource_list_add_tail(iospace, &info->io_resources);
 
+	/* Adjust base of original IO port resource descriptor */
 	entry->offset = base_port;
-	res->start = min + base_port;
-	res->end = max + base_port;
-	resource_list_add_tail(iospace, &info->io_resources);
+	res->start += base_port;
+	res->end += base_port;
 
 	return 0;
 
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index cdc5c2599beb..6578f68b17be 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -190,8 +190,7 @@ static bool acpi_decode_space(struct resource_win *win,
 {
 	u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;
 	bool wp = addr->info.mem.write_protect;
-	u64 len = attr->address_length;
-	u64 start, end, offset = 0;
+	u64 len = attr->address_length, offset = 0;
 	struct resource *res = &win->res;
 
 	/*
@@ -215,14 +214,13 @@ static bool acpi_decode_space(struct resource_win *win,
 	else if (attr->translation_offset)
 		pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",
 			 attr->translation_offset);
-	start = attr->minimum + offset;
-	end = attr->maximum + offset;
 
 	win->offset = offset;
-	res->start = start;
-	res->end = end;
+	res->start = attr->minimum;
+	res->end = attr->maximum;
 	if (sizeof(resource_size_t) < sizeof(u64) &&
-	    (offset != win->offset || start != res->start || end != res->end)) {
+	    (offset != win->offset || attr->minimum != res->start ||
+	     attr->maximum != res->end)) {
 		pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",
 			attr->minimum, attr->maximum);
 		return false;
-- 
1.7.10.4


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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-10  5:50                       ` Jiang Liu
@ 2015-11-11 17:46                         ` Lorenzo Pieralisi
  2015-11-11 18:12                             ` Liviu Dudau
                                             ` (2 more replies)
  0 siblings, 3 replies; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-11 17:46 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Arnd Bergmann, Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:

[...]

> >> In particular, I would like to understand, for an eg DWordIO descriptor,
> >> what Range Minimum, Range Maximum and Translation Offset represent,
> >> they can't mean different things depending on the SW parsing them,
> >> this totally defeats the purpose.
> > 
> > I have no clue about what those mean in ACPI though.
> > 
> > Generally speaking, each PCI domain is expected to have a (normally 64KB)
> > range of CPU addresses that gets translated into PCI I/O space the same
> > way that config space and memory space are handled.
> > This is true for almost every architecture except for x86, which uses
> > different CPU instructions for I/O space compared to the other spaces.
> > 
> >> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
> >> basically that's the CPU physical address at which the PCI host bridge
> >> map the IO space transactions), I do not think ia64 is any different from
> >> arm64 in this respect, if it is please provide an HW description here from
> >> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
> >> tables would help).
> > 
> > The main difference between ia64 and a lot of the other architectures (e.g.
> > sparc is different again) is that ia64 defines a logical address range
> > in terms of having a small number for each I/O space followed by the
> > offset within that space as a 'port number' and uses a mapping function
> > that is defined as
> > 
> > static inline void *__ia64_mk_io_addr (unsigned long port)
> > {
> >         struct io_space *space = &io_space[IO_SPACE_NR(port)];
> >         return (space->mmio_base | IO_SPACE_PORT(port););
> > }
> > static inline unsigned int inl(unsigned long port)
> > {
> >         return *__ia64_mk_io_addr(port);
> > }
> > 
> > Most architectures allow only one I/O port range and put it at a fixed
> > virtual address so that inl() simply becomes 
> > 
> > static inline u32 inl(unsigned long addr)
> > {
> >         return readl(PCI_IOBASE + addr);
> > }
> > 
> > which noticeably reduces code size.
> > 
> > On some architectures (powerpc, arm, arm64), we then get the same simplified
> > definition with a fixed virtual address, and use pci_ioremap_io() or
> > something like that to to map a physical address range into this virtual
> > address window at the correct io_offset;
> Hi all,
> 	Thanks for explanation, I found a way to make the ACPI resource
> parsing interface arch neutral, it should help to address Lorenzo's
> concern. Please refer to the attached patch. (It's still RFC, not tested
> yet).

If we go with this approach though, you are not adding the offset to
the resource when parsing the memory spaces in acpi_decode_space(), are we
sure that's what we really want ?

In DT, a host bridge range has a:

- CPU physical address
- PCI bus address

We use that to compute the offset between primary bus (ie CPU physical
address) and secondary bus (ie PCI bus address).

The value ending up in the PCI resource struct (for memory space) is
the CPU physical address, if you do not add the offset in acpi_decode_space
that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
am I wrong ?

Overall I think the point is related to ioport_resource and its check
in acpi_pci_root_validate_resources() which basically that's the
problem that started this thread.

On arm64, IO_SPACE_LIMIT is 16M, which, AFAIK is a kernel limit, not
a HW one. Comparing the resources parsed from the PCI bridge _CRS against
the range 0..IO_SPACE_LIMIT is not necessarily meaningful (or at least
not meaningful in its current form), on ia64 it works because IO_SPACE_LIMIT
is bumped up to 4G, that's the reason why adding the offset to the ACPI IO
resources work on ia64 as far as I understand.

And that's why I pulled Arnd in this discussion since he knows better
than me: what does ioport_resource _really_ represent on ARM64 ? It seems
to me that it is a range of IO ports values (ie a window that defines
the allowed offset in the virtual address space allocated to PCI IO) that
has _nothing_ to do with the CPU physical address at which the IO space is
actually mapped.

To sum it up for a, say, DWordIo/Memory descriptor:

- AddressMinimum, AddressMaximum represent the PCI bus addresses defining
  the resource start..end
- AddressTranslation is the offset that has to be added to AddressMinimum
  and AddressMaximum to get the window in CPU physical address space

So:

- Either we go with the patch attached (but please check my comment on
  the memory spaces)
- Or we patch acpi_pci_root_validate_resources() to amend the way
  IORESOURCE_IO is currently checked against ioport_resource, it can't
  work on arm64 at present, I described why above

Thoughts appreciated it is time we got this sorted and thanks for
the patch.

Thanks,
Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-11 17:46                         ` Lorenzo Pieralisi
@ 2015-11-11 18:12                             ` Liviu Dudau
  2015-11-11 20:55                           ` Arnd Bergmann
  2015-11-12  8:43                           ` Jiang Liu
  2 siblings, 0 replies; 56+ messages in thread
From: Liviu Dudau @ 2015-11-11 18:12 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Jiang Liu, Arnd Bergmann, Tomasz Nowicki, Bjorn Helgaas,
	Rafael J . Wysocki, Marc Zyngier, Hanjun Guo, linux-acpi,
	linux-pci, linux-kernel, x86

On Wed, Nov 11, 2015 at 05:46:47PM +0000, Lorenzo Pieralisi wrote:
> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
> 
> [...]
> 
> > >> In particular, I would like to understand, for an eg DWordIO descriptor,
> > >> what Range Minimum, Range Maximum and Translation Offset represent,
> > >> they can't mean different things depending on the SW parsing them,
> > >> this totally defeats the purpose.
> > > 
> > > I have no clue about what those mean in ACPI though.
> > > 
> > > Generally speaking, each PCI domain is expected to have a (normally 64KB)
> > > range of CPU addresses that gets translated into PCI I/O space the same
> > > way that config space and memory space are handled.
> > > This is true for almost every architecture except for x86, which uses
> > > different CPU instructions for I/O space compared to the other spaces.
> > > 
> > >> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
> > >> basically that's the CPU physical address at which the PCI host bridge
> > >> map the IO space transactions), I do not think ia64 is any different from
> > >> arm64 in this respect, if it is please provide an HW description here from
> > >> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
> > >> tables would help).
> > > 
> > > The main difference between ia64 and a lot of the other architectures (e.g.
> > > sparc is different again) is that ia64 defines a logical address range
> > > in terms of having a small number for each I/O space followed by the
> > > offset within that space as a 'port number' and uses a mapping function
> > > that is defined as
> > > 
> > > static inline void *__ia64_mk_io_addr (unsigned long port)
> > > {
> > >         struct io_space *space = &io_space[IO_SPACE_NR(port)];
> > >         return (space->mmio_base | IO_SPACE_PORT(port););
> > > }
> > > static inline unsigned int inl(unsigned long port)
> > > {
> > >         return *__ia64_mk_io_addr(port);
> > > }
> > > 
> > > Most architectures allow only one I/O port range and put it at a fixed
> > > virtual address so that inl() simply becomes 
> > > 
> > > static inline u32 inl(unsigned long addr)
> > > {
> > >         return readl(PCI_IOBASE + addr);
> > > }
> > > 
> > > which noticeably reduces code size.
> > > 
> > > On some architectures (powerpc, arm, arm64), we then get the same simplified
> > > definition with a fixed virtual address, and use pci_ioremap_io() or
> > > something like that to to map a physical address range into this virtual
> > > address window at the correct io_offset;
> > Hi all,
> > 	Thanks for explanation, I found a way to make the ACPI resource
> > parsing interface arch neutral, it should help to address Lorenzo's
> > concern. Please refer to the attached patch. (It's still RFC, not tested
> > yet).
> 
> If we go with this approach though, you are not adding the offset to
> the resource when parsing the memory spaces in acpi_decode_space(), are we
> sure that's what we really want ?
> 
> In DT, a host bridge range has a:
> 
> - CPU physical address
> - PCI bus address
> 
> We use that to compute the offset between primary bus (ie CPU physical
> address) and secondary bus (ie PCI bus address).
> 
> The value ending up in the PCI resource struct (for memory space) is
> the CPU physical address, if you do not add the offset in acpi_decode_space
> that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
> am I wrong ?
> 
> Overall I think the point is related to ioport_resource and its check
> in acpi_pci_root_validate_resources() which basically that's the
> problem that started this thread.
> 
> On arm64, IO_SPACE_LIMIT is 16M, which, AFAIK is a kernel limit, not
> a HW one. 

You're right, it is a kernel limit. There is no HW limit for IO on arm64.

> Comparing the resources parsed from the PCI bridge _CRS against
> the range 0..IO_SPACE_LIMIT is not necessarily meaningful (or at least
> not meaningful in its current form), on ia64 it works because IO_SPACE_LIMIT
> is bumped up to 4G, that's the reason why adding the offset to the ACPI IO
> resources work on ia64 as far as I understand.
> 
> And that's why I pulled Arnd in this discussion since he knows better
> than me: what does ioport_resource _really_ represent on ARM64 ? It seems
> to me that it is a range of IO ports values (ie a window that defines
> the allowed offset in the virtual address space allocated to PCI IO) that
> has _nothing_ to do with the CPU physical address at which the IO space is
> actually mapped.

Correct. The idea is that you can have any number of host bridges and what
you get back for an ioport_resource is a window inside the host bridge IO
space. That space is also offset-ed inside the kernel's IO port space
(0..IO_SPACE_LIMIT) by the amount of space already taken by preceeding
host bridges, so that two ioport_resources comming from two different
host bridges don't overlap in the CPU address space.

Best regards,
Liviu


> 
> To sum it up for a, say, DWordIo/Memory descriptor:
> 
> - AddressMinimum, AddressMaximum represent the PCI bus addresses defining
>   the resource start..end
> - AddressTranslation is the offset that has to be added to AddressMinimum
>   and AddressMaximum to get the window in CPU physical address space
> 
> So:
> 
> - Either we go with the patch attached (but please check my comment on
>   the memory spaces)
> - Or we patch acpi_pci_root_validate_resources() to amend the way
>   IORESOURCE_IO is currently checked against ioport_resource, it can't
>   work on arm64 at present, I described why above
> 
> Thoughts appreciated it is time we got this sorted and thanks for
> the patch.
> 
> Thanks,
> Lorenzo
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
@ 2015-11-11 18:12                             ` Liviu Dudau
  0 siblings, 0 replies; 56+ messages in thread
From: Liviu Dudau @ 2015-11-11 18:12 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Jiang Liu, Arnd Bergmann, Tomasz Nowicki, Bjorn Helgaas,
	Rafael J . Wysocki, Marc Zyngier, Hanjun Guo, linux-acpi,
	linux-pci, linux-kernel, x86

On Wed, Nov 11, 2015 at 05:46:47PM +0000, Lorenzo Pieralisi wrote:
> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
> 
> [...]
> 
> > >> In particular, I would like to understand, for an eg DWordIO descriptor,
> > >> what Range Minimum, Range Maximum and Translation Offset represent,
> > >> they can't mean different things depending on the SW parsing them,
> > >> this totally defeats the purpose.
> > > 
> > > I have no clue about what those mean in ACPI though.
> > > 
> > > Generally speaking, each PCI domain is expected to have a (normally 64KB)
> > > range of CPU addresses that gets translated into PCI I/O space the same
> > > way that config space and memory space are handled.
> > > This is true for almost every architecture except for x86, which uses
> > > different CPU instructions for I/O space compared to the other spaces.
> > > 
> > >> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
> > >> basically that's the CPU physical address at which the PCI host bridge
> > >> map the IO space transactions), I do not think ia64 is any different from
> > >> arm64 in this respect, if it is please provide an HW description here from
> > >> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
> > >> tables would help).
> > > 
> > > The main difference between ia64 and a lot of the other architectures (e.g.
> > > sparc is different again) is that ia64 defines a logical address range
> > > in terms of having a small number for each I/O space followed by the
> > > offset within that space as a 'port number' and uses a mapping function
> > > that is defined as
> > > 
> > > static inline void *__ia64_mk_io_addr (unsigned long port)
> > > {
> > >         struct io_space *space = &io_space[IO_SPACE_NR(port)];
> > >         return (space->mmio_base | IO_SPACE_PORT(port););
> > > }
> > > static inline unsigned int inl(unsigned long port)
> > > {
> > >         return *__ia64_mk_io_addr(port);
> > > }
> > > 
> > > Most architectures allow only one I/O port range and put it at a fixed
> > > virtual address so that inl() simply becomes 
> > > 
> > > static inline u32 inl(unsigned long addr)
> > > {
> > >         return readl(PCI_IOBASE + addr);
> > > }
> > > 
> > > which noticeably reduces code size.
> > > 
> > > On some architectures (powerpc, arm, arm64), we then get the same simplified
> > > definition with a fixed virtual address, and use pci_ioremap_io() or
> > > something like that to to map a physical address range into this virtual
> > > address window at the correct io_offset;
> > Hi all,
> > 	Thanks for explanation, I found a way to make the ACPI resource
> > parsing interface arch neutral, it should help to address Lorenzo's
> > concern. Please refer to the attached patch. (It's still RFC, not tested
> > yet).
> 
> If we go with this approach though, you are not adding the offset to
> the resource when parsing the memory spaces in acpi_decode_space(), are we
> sure that's what we really want ?
> 
> In DT, a host bridge range has a:
> 
> - CPU physical address
> - PCI bus address
> 
> We use that to compute the offset between primary bus (ie CPU physical
> address) and secondary bus (ie PCI bus address).
> 
> The value ending up in the PCI resource struct (for memory space) is
> the CPU physical address, if you do not add the offset in acpi_decode_space
> that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
> am I wrong ?
> 
> Overall I think the point is related to ioport_resource and its check
> in acpi_pci_root_validate_resources() which basically that's the
> problem that started this thread.
> 
> On arm64, IO_SPACE_LIMIT is 16M, which, AFAIK is a kernel limit, not
> a HW one. 

You're right, it is a kernel limit. There is no HW limit for IO on arm64.

> Comparing the resources parsed from the PCI bridge _CRS against
> the range 0..IO_SPACE_LIMIT is not necessarily meaningful (or at least
> not meaningful in its current form), on ia64 it works because IO_SPACE_LIMIT
> is bumped up to 4G, that's the reason why adding the offset to the ACPI IO
> resources work on ia64 as far as I understand.
> 
> And that's why I pulled Arnd in this discussion since he knows better
> than me: what does ioport_resource _really_ represent on ARM64 ? It seems
> to me that it is a range of IO ports values (ie a window that defines
> the allowed offset in the virtual address space allocated to PCI IO) that
> has _nothing_ to do with the CPU physical address at which the IO space is
> actually mapped.

Correct. The idea is that you can have any number of host bridges and what
you get back for an ioport_resource is a window inside the host bridge IO
space. That space is also offset-ed inside the kernel's IO port space
(0..IO_SPACE_LIMIT) by the amount of space already taken by preceeding
host bridges, so that two ioport_resources comming from two different
host bridges don't overlap in the CPU address space.

Best regards,
Liviu


> 
> To sum it up for a, say, DWordIo/Memory descriptor:
> 
> - AddressMinimum, AddressMaximum represent the PCI bus addresses defining
>   the resource start..end
> - AddressTranslation is the offset that has to be added to AddressMinimum
>   and AddressMaximum to get the window in CPU physical address space
> 
> So:
> 
> - Either we go with the patch attached (but please check my comment on
>   the memory spaces)
> - Or we patch acpi_pci_root_validate_resources() to amend the way
>   IORESOURCE_IO is currently checked against ioport_resource, it can't
>   work on arm64 at present, I described why above
> 
> Thoughts appreciated it is time we got this sorted and thanks for
> the patch.
> 
> Thanks,
> Lorenzo
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-11 17:46                         ` Lorenzo Pieralisi
  2015-11-11 18:12                             ` Liviu Dudau
@ 2015-11-11 20:55                           ` Arnd Bergmann
  2015-11-12 12:08                             ` Lorenzo Pieralisi
  2015-11-12  8:43                           ` Jiang Liu
  2 siblings, 1 reply; 56+ messages in thread
From: Arnd Bergmann @ 2015-11-11 20:55 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Jiang Liu, Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Wednesday 11 November 2015 17:46:47 Lorenzo Pieralisi wrote:
> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
> If we go with this approach though, you are not adding the offset to
> the resource when parsing the memory spaces in acpi_decode_space(), are we
> sure that's what we really want ?
> 
> In DT, a host bridge range has a:
> 
> - CPU physical address
> - PCI bus address
> 
> We use that to compute the offset between primary bus (ie CPU physical
> address) and secondary bus (ie PCI bus address).
> 
> The value ending up in the PCI resource struct (for memory space) is
> the CPU physical address, if you do not add the offset in acpi_decode_space
> that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
> am I wrong ?

Sinan Kaya pointed out that SBSA mandates a 1:1 mapping for memory space.

> On arm64, IO_SPACE_LIMIT is 16M, which, AFAIK is a kernel limit, not
> a HW one. Comparing the resources parsed from the PCI bridge _CRS against
> the range 0..IO_SPACE_LIMIT is not necessarily meaningful (or at least
> not meaningful in its current form), on ia64 it works because IO_SPACE_LIMIT
> is bumped up to 4G, that's the reason why adding the offset to the ACPI IO
> resources work on ia64 as far as I understand.
> 
> And that's why I pulled Arnd in this discussion since he knows better
> than me: what does ioport_resource _really_ represent on ARM64 ? It seems
> to me that it is a range of IO ports values (ie a window that defines
> the allowed offset in the virtual address space allocated to PCI IO) that
> has _nothing_ to do with the CPU physical address at which the IO space is
> actually mapped.

Right, the ioport_resource uses the same space as the CPU virtual address,
with an offset of PCI_IOBASE that is defined as

#define PCI_IOBASE            ((void __iomem *)PCI_IO_VIRT_BASE)
#define PCI_IO_START            (PCI_IO_END - PCI_IO_SIZE)
#define PCI_IO_END              (MODULES_VADDR - SZ_2M)
#define PCI_IO_SIZE             SZ_16M

> To sum it up for a, say, DWordIo/Memory descriptor:
> 
> - AddressMinimum, AddressMaximum represent the PCI bus addresses defining
>   the resource start..end
> - AddressTranslation is the offset that has to be added to AddressMinimum
>   and AddressMaximum to get the window in CPU physical address space
> 
> So:
> 
> - Either we go with the patch attached (but please check my comment on
>   the memory spaces)
> - Or we patch acpi_pci_root_validate_resources() to amend the way
>   IORESOURCE_IO is currently checked against ioport_resource, it can't
>   work on arm64 at present, I described why above
> 
> Thoughts appreciated it is time we got this sorted and thanks for
> the patch.

The easiest way would be to assume that nobody is building a server
system that has multiple I/O spaces. SBSA explicitly makes I/O space
optional, and really the only reason anyone includes that feature these
days is for initializing GPUs through the BIOS POST method, so that
is not relevant for servers. Even when you do have multiple PCIe
host controllers that all support I/O space, the most logical implementation
would be to share one common space.

If that fails, there are still two cases you have to care about, and
it really depends on what hardware makers decide to use here (and whether
we have any influence over them). The easier way for us to do this is
if every hardware sets up the mapping between CPU physical and PCI I/O
in a way that the I/O space numbers are non-overlapping between the
host controllers. That way we can still make Linux ioport_resource
addresses the same as PCI I/O space addresses (using io_offset=0),
with the downside being that only the first PCIe host (as enumerated
by the bootloader) can have I/O space addresses below 1024 that may
be required for ISA compatibility on some hardware.

	Arnd

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-11 17:46                         ` Lorenzo Pieralisi
  2015-11-11 18:12                             ` Liviu Dudau
  2015-11-11 20:55                           ` Arnd Bergmann
@ 2015-11-12  8:43                           ` Jiang Liu
  2015-11-12 13:21                             ` Tomasz Nowicki
  2 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-12  8:43 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Arnd Bergmann, Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On 2015/11/12 1:46, Lorenzo Pieralisi wrote:
> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
> 
> [...]
> 
>>>> In particular, I would like to understand, for an eg DWordIO descriptor,
>>>> what Range Minimum, Range Maximum and Translation Offset represent,
>>>> they can't mean different things depending on the SW parsing them,
>>>> this totally defeats the purpose.
>>>
>>> I have no clue about what those mean in ACPI though.
>>>
>>> Generally speaking, each PCI domain is expected to have a (normally 64KB)
>>> range of CPU addresses that gets translated into PCI I/O space the same
>>> way that config space and memory space are handled.
>>> This is true for almost every architecture except for x86, which uses
>>> different CPU instructions for I/O space compared to the other spaces.
>>>
>>>> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
>>>> basically that's the CPU physical address at which the PCI host bridge
>>>> map the IO space transactions), I do not think ia64 is any different from
>>>> arm64 in this respect, if it is please provide an HW description here from
>>>> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
>>>> tables would help).
>>>
>>> The main difference between ia64 and a lot of the other architectures (e.g.
>>> sparc is different again) is that ia64 defines a logical address range
>>> in terms of having a small number for each I/O space followed by the
>>> offset within that space as a 'port number' and uses a mapping function
>>> that is defined as
>>>
>>> static inline void *__ia64_mk_io_addr (unsigned long port)
>>> {
>>>         struct io_space *space = &io_space[IO_SPACE_NR(port)];
>>>         return (space->mmio_base | IO_SPACE_PORT(port););
>>> }
>>> static inline unsigned int inl(unsigned long port)
>>> {
>>>         return *__ia64_mk_io_addr(port);
>>> }
>>>
>>> Most architectures allow only one I/O port range and put it at a fixed
>>> virtual address so that inl() simply becomes 
>>>
>>> static inline u32 inl(unsigned long addr)
>>> {
>>>         return readl(PCI_IOBASE + addr);
>>> }
>>>
>>> which noticeably reduces code size.
>>>
>>> On some architectures (powerpc, arm, arm64), we then get the same simplified
>>> definition with a fixed virtual address, and use pci_ioremap_io() or
>>> something like that to to map a physical address range into this virtual
>>> address window at the correct io_offset;
>> Hi all,
>> 	Thanks for explanation, I found a way to make the ACPI resource
>> parsing interface arch neutral, it should help to address Lorenzo's
>> concern. Please refer to the attached patch. (It's still RFC, not tested
>> yet).
> 
> If we go with this approach though, you are not adding the offset to
> the resource when parsing the memory spaces in acpi_decode_space(), are we
> sure that's what we really want ?
> 
> In DT, a host bridge range has a:
> 
> - CPU physical address
> - PCI bus address
> 
> We use that to compute the offset between primary bus (ie CPU physical
> address) and secondary bus (ie PCI bus address).
> 
> The value ending up in the PCI resource struct (for memory space) is
> the CPU physical address, if you do not add the offset in acpi_decode_space
> that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
> am I wrong ?
Hi Lorenzo,
	I may have found the divergence between us about the design here. You
treat it as a one-stage translation but I treat it as a
two-stage translation as below:
stage 1: map(translate) per-PCI-domain IO port address[0, 16M) into
system global IO port address. Here system global IO port address is
ioport_resource[0, IO_SPACE_LIMIT).
stage 2: map system IO port address into system memory address.

We need two objects of struct resource_win to support above two-stage
translation. One object, type of IORESOURCE_IO, is used to support
stage one, and it will also used to allocate IO port resources
for PCI devices. Another object, type of IORESOURCE_MMIO, is used
to allocate resource from iomem_resource and setup MMIO mapping
to actually access IO ports.

For ARM64, it doesn't support multiple per-PCI-domain(bus local)
IO port address space yet, so stage one seems to be optional
becomes the offset between bus local IO port address and system
IO port address is always 0. But we still need two objects of
struct resource_win. The first object is
	{
		offset:0,
		start:AddressMinimum,
		end:AddressMaximum,
		flags:IORESOURCE_IO
	}
Here it's type of IORESOURCE_IO and offset must be zero because
pcibios_resource_to_bus() will access it translate system IO
port address into bus local IO port address. With my patch,
the struct resource_win object created by the ACPI core will
be reused for this.

The second object is:
	{
		offset:Translation_Offset,
		start:AddressMinimum + Translation_Offset,
		end:AddressMaximum + Translation_Offset,
		flags:IORESOURCE_MMIO
	}
Arch code need to create the second struct resource_win object
and actually setup the MMIO mapping.

But there's really another bug need to get fixed, funciton
acpi_dev_ioresource_flags() assumes bus local IO port address
space is size of 64K, which is wrong for IA64 and ARM64.

Thanks,
Gerry

> 
> Overall I think the point is related to ioport_resource and its check
> in acpi_pci_root_validate_resources() which basically that's the
> problem that started this thread.
> 
> On arm64, IO_SPACE_LIMIT is 16M, which, AFAIK is a kernel limit, not
> a HW one. Comparing the resources parsed from the PCI bridge _CRS against
> the range 0..IO_SPACE_LIMIT is not necessarily meaningful (or at least
> not meaningful in its current form), on ia64 it works because IO_SPACE_LIMIT
> is bumped up to 4G, that's the reason why adding the offset to the ACPI IO
> resources work on ia64 as far as I understand.
> 
> And that's why I pulled Arnd in this discussion since he knows better
> than me: what does ioport_resource _really_ represent on ARM64 ? It seems
> to me that it is a range of IO ports values (ie a window that defines
> the allowed offset in the virtual address space allocated to PCI IO) that
> has _nothing_ to do with the CPU physical address at which the IO space is
> actually mapped.
> 
> To sum it up for a, say, DWordIo/Memory descriptor:
> 
> - AddressMinimum, AddressMaximum represent the PCI bus addresses defining
>   the resource start..end
> - AddressTranslation is the offset that has to be added to AddressMinimum
>   and AddressMaximum to get the window in CPU physical address space
> 
> So:
> 
> - Either we go with the patch attached (but please check my comment on
>   the memory spaces)
> - Or we patch acpi_pci_root_validate_resources() to amend the way
>   IORESOURCE_IO is currently checked against ioport_resource, it can't
>   work on arm64 at present, I described why above
> 
> Thoughts appreciated it is time we got this sorted and thanks for
> the patch.
> 
> Thanks,
> Lorenzo
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-11 20:55                           ` Arnd Bergmann
@ 2015-11-12 12:08                             ` Lorenzo Pieralisi
  0 siblings, 0 replies; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-12 12:08 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Jiang Liu, Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

On Wed, Nov 11, 2015 at 09:55:37PM +0100, Arnd Bergmann wrote:
> On Wednesday 11 November 2015 17:46:47 Lorenzo Pieralisi wrote:
> > On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
> > If we go with this approach though, you are not adding the offset to
> > the resource when parsing the memory spaces in acpi_decode_space(), are we
> > sure that's what we really want ?
> > 
> > In DT, a host bridge range has a:
> > 
> > - CPU physical address
> > - PCI bus address
> > 
> > We use that to compute the offset between primary bus (ie CPU physical
> > address) and secondary bus (ie PCI bus address).
> > 
> > The value ending up in the PCI resource struct (for memory space) is
> > the CPU physical address, if you do not add the offset in acpi_decode_space
> > that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
> > am I wrong ?
> 
> Sinan Kaya pointed out that SBSA mandates a 1:1 mapping for memory space.

acpi_decode_space() is generic code though, it has to work on all arches,
I was worried about triggering regressions on x86 and ia64 here.

[...]

> > To sum it up for a, say, DWordIo/Memory descriptor:
> > 
> > - AddressMinimum, AddressMaximum represent the PCI bus addresses defining
> >   the resource start..end
> > - AddressTranslation is the offset that has to be added to AddressMinimum
> >   and AddressMaximum to get the window in CPU physical address space
> > 
> > So:
> > 
> > - Either we go with the patch attached (but please check my comment on
> >   the memory spaces)
> > - Or we patch acpi_pci_root_validate_resources() to amend the way
> >   IORESOURCE_IO is currently checked against ioport_resource, it can't
> >   work on arm64 at present, I described why above
> > 
> > Thoughts appreciated it is time we got this sorted and thanks for
> > the patch.
> 
> The easiest way would be to assume that nobody is building a server
> system that has multiple I/O spaces. SBSA explicitly makes I/O space
> optional, and really the only reason anyone includes that feature these
> days is for initializing GPUs through the BIOS POST method, so that
> is not relevant for servers. Even when you do have multiple PCIe
> host controllers that all support I/O space, the most logical implementation
> would be to share one common space.
> 
> If that fails, there are still two cases you have to care about, and
> it really depends on what hardware makers decide to use here (and whether
> we have any influence over them). The easier way for us to do this is
> if every hardware sets up the mapping between CPU physical and PCI I/O
> in a way that the I/O space numbers are non-overlapping between the
> host controllers. That way we can still make Linux ioport_resource
> addresses the same as PCI I/O space addresses (using io_offset=0),
> with the downside being that only the first PCIe host (as enumerated
> by the bootloader) can have I/O space addresses below 1024 that may
> be required for ISA compatibility on some hardware.

Yes, I think the approach we have in place on arm64 sound, I will work with
Jiang to make sure we interpret and manage IO space on arm64 the same
way we do with DT, I do not expect any issue on that side, I was more
worried about the interpretation of ACPI tables, I really really do not
want to end up with ACPI tables that are set-up in a way that can cause
regressions, we have to agree (and make it crystal clear in the ACPI
specs) what the resource descriptors define and how, then the ACPI kernel
resource layer should be made compliant.

Thanks,
Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-12  8:43                           ` Jiang Liu
@ 2015-11-12 13:21                             ` Tomasz Nowicki
  2015-11-12 14:04                               ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-12 13:21 UTC (permalink / raw)
  To: Jiang Liu, Lorenzo Pieralisi
  Cc: Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 12.11.2015 09:43, Jiang Liu wrote:
> On 2015/11/12 1:46, Lorenzo Pieralisi wrote:
>> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
>>
>> [...]
>>
>>>>> In particular, I would like to understand, for an eg DWordIO descriptor,
>>>>> what Range Minimum, Range Maximum and Translation Offset represent,
>>>>> they can't mean different things depending on the SW parsing them,
>>>>> this totally defeats the purpose.
>>>>
>>>> I have no clue about what those mean in ACPI though.
>>>>
>>>> Generally speaking, each PCI domain is expected to have a (normally 64KB)
>>>> range of CPU addresses that gets translated into PCI I/O space the same
>>>> way that config space and memory space are handled.
>>>> This is true for almost every architecture except for x86, which uses
>>>> different CPU instructions for I/O space compared to the other spaces.
>>>>
>>>>> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
>>>>> basically that's the CPU physical address at which the PCI host bridge
>>>>> map the IO space transactions), I do not think ia64 is any different from
>>>>> arm64 in this respect, if it is please provide an HW description here from
>>>>> the PCI bus perspective here (also an example of ia64 ACPI PCI host bridge
>>>>> tables would help).
>>>>
>>>> The main difference between ia64 and a lot of the other architectures (e.g.
>>>> sparc is different again) is that ia64 defines a logical address range
>>>> in terms of having a small number for each I/O space followed by the
>>>> offset within that space as a 'port number' and uses a mapping function
>>>> that is defined as
>>>>
>>>> static inline void *__ia64_mk_io_addr (unsigned long port)
>>>> {
>>>>          struct io_space *space = &io_space[IO_SPACE_NR(port)];
>>>>          return (space->mmio_base | IO_SPACE_PORT(port););
>>>> }
>>>> static inline unsigned int inl(unsigned long port)
>>>> {
>>>>          return *__ia64_mk_io_addr(port);
>>>> }
>>>>
>>>> Most architectures allow only one I/O port range and put it at a fixed
>>>> virtual address so that inl() simply becomes
>>>>
>>>> static inline u32 inl(unsigned long addr)
>>>> {
>>>>          return readl(PCI_IOBASE + addr);
>>>> }
>>>>
>>>> which noticeably reduces code size.
>>>>
>>>> On some architectures (powerpc, arm, arm64), we then get the same simplified
>>>> definition with a fixed virtual address, and use pci_ioremap_io() or
>>>> something like that to to map a physical address range into this virtual
>>>> address window at the correct io_offset;
>>> Hi all,
>>> 	Thanks for explanation, I found a way to make the ACPI resource
>>> parsing interface arch neutral, it should help to address Lorenzo's
>>> concern. Please refer to the attached patch. (It's still RFC, not tested
>>> yet).
>>
>> If we go with this approach though, you are not adding the offset to
>> the resource when parsing the memory spaces in acpi_decode_space(), are we
>> sure that's what we really want ?
>>
>> In DT, a host bridge range has a:
>>
>> - CPU physical address
>> - PCI bus address
>>
>> We use that to compute the offset between primary bus (ie CPU physical
>> address) and secondary bus (ie PCI bus address).
>>
>> The value ending up in the PCI resource struct (for memory space) is
>> the CPU physical address, if you do not add the offset in acpi_decode_space
>> that does not hold true on platforms where CPU<->PCI offset != 0 on ACPI,
>> am I wrong ?
> Hi Lorenzo,
> 	I may have found the divergence between us about the design here. You
> treat it as a one-stage translation but I treat it as a
> two-stage translation as below:
> stage 1: map(translate) per-PCI-domain IO port address[0, 16M) into
> system global IO port address. Here system global IO port address is
> ioport_resource[0, IO_SPACE_LIMIT).
> stage 2: map system IO port address into system memory address.
>
> We need two objects of struct resource_win to support above two-stage
> translation. One object, type of IORESOURCE_IO, is used to support
> stage one, and it will also used to allocate IO port resources
> for PCI devices. Another object, type of IORESOURCE_MMIO, is used
> to allocate resource from iomem_resource and setup MMIO mapping
> to actually access IO ports.
>
> For ARM64, it doesn't support multiple per-PCI-domain(bus local)
> IO port address space yet, so stage one seems to be optional
> becomes the offset between bus local IO port address and system
> IO port address is always 0. But we still need two objects of
> struct resource_win. The first object is
> 	{
> 		offset:0,
> 		start:AddressMinimum,
> 		end:AddressMaximum,
> 		flags:IORESOURCE_IO
> 	}
> Here it's type of IORESOURCE_IO and offset must be zero because
> pcibios_resource_to_bus() will access it translate system IO
> port address into bus local IO port address. With my patch,
> the struct resource_win object created by the ACPI core will
> be reused for this.
>
> The second object is:
> 	{
> 		offset:Translation_Offset,
> 		start:AddressMinimum + Translation_Offset,
> 		end:AddressMaximum + Translation_Offset,
> 		flags:IORESOURCE_MMIO
> 	}
> Arch code need to create the second struct resource_win object
> and actually setup the MMIO mapping.
>
> But there's really another bug need to get fixed, funciton
> acpi_dev_ioresource_flags() assumes bus local IO port address
> space is size of 64K, which is wrong for IA64 and ARM64.
>

So what would be the Translation_Offset meaning for two cases DWordIo 
(....,TypeTranslation) vs DWordIo (....,TypeStatic)? And why we did not 
use TypeTranslation for IA64 so far?

I am worried that TypeTranslation fall into the IA64 category but ACPI 
tables were already written incorrectly.

Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-12 13:21                             ` Tomasz Nowicki
@ 2015-11-12 14:04                               ` Jiang Liu
  2015-11-12 14:45                                 ` Tomasz Nowicki
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-12 14:04 UTC (permalink / raw)
  To: Tomasz Nowicki, Lorenzo Pieralisi
  Cc: Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 2015/11/12 21:21, Tomasz Nowicki wrote:
> On 12.11.2015 09:43, Jiang Liu wrote:
>> On 2015/11/12 1:46, Lorenzo Pieralisi wrote:
>>> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
>>>
>>> [...]
>>>
>>>>>> In particular, I would like to understand, for an eg DWordIO
>>>>>> descriptor,
>>>>>> what Range Minimum, Range Maximum and Translation Offset represent,
>>>>>> they can't mean different things depending on the SW parsing them,
>>>>>> this totally defeats the purpose.
>>>>>
>>>>> I have no clue about what those mean in ACPI though.
>>>>>
>>>>> Generally speaking, each PCI domain is expected to have a (normally
>>>>> 64KB)
>>>>> range of CPU addresses that gets translated into PCI I/O space the
>>>>> same
>>>>> way that config space and memory space are handled.
>>>>> This is true for almost every architecture except for x86, which uses
>>>>> different CPU instructions for I/O space compared to the other spaces.
>>>>>
>>>>>> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
>>>>>> basically that's the CPU physical address at which the PCI host
>>>>>> bridge
>>>>>> map the IO space transactions), I do not think ia64 is any
>>>>>> different from
>>>>>> arm64 in this respect, if it is please provide an HW description
>>>>>> here from
>>>>>> the PCI bus perspective here (also an example of ia64 ACPI PCI
>>>>>> host bridge
>>>>>> tables would help).
>>>>>
>>>>> The main difference between ia64 and a lot of the other
>>>>> architectures (e.g.
>>>>> sparc is different again) is that ia64 defines a logical address range
>>>>> in terms of having a small number for each I/O space followed by the
>>>>> offset within that space as a 'port number' and uses a mapping
>>>>> function
>>>>> that is defined as
>>>>>
>>>>> static inline void *__ia64_mk_io_addr (unsigned long port)
>>>>> {
>>>>>          struct io_space *space = &io_space[IO_SPACE_NR(port)];
>>>>>          return (space->mmio_base | IO_SPACE_PORT(port););
>>>>> }
>>>>> static inline unsigned int inl(unsigned long port)
>>>>> {
>>>>>          return *__ia64_mk_io_addr(port);
>>>>> }
>>>>>
>>>>> Most architectures allow only one I/O port range and put it at a fixed
>>>>> virtual address so that inl() simply becomes
>>>>>
>>>>> static inline u32 inl(unsigned long addr)
>>>>> {
>>>>>          return readl(PCI_IOBASE + addr);
>>>>> }
>>>>>
>>>>> which noticeably reduces code size.
>>>>>
>>>>> On some architectures (powerpc, arm, arm64), we then get the same
>>>>> simplified
>>>>> definition with a fixed virtual address, and use pci_ioremap_io() or
>>>>> something like that to to map a physical address range into this
>>>>> virtual
>>>>> address window at the correct io_offset;
>>>> Hi all,
>>>>     Thanks for explanation, I found a way to make the ACPI resource
>>>> parsing interface arch neutral, it should help to address Lorenzo's
>>>> concern. Please refer to the attached patch. (It's still RFC, not
>>>> tested
>>>> yet).
>>>
>>> If we go with this approach though, you are not adding the offset to
>>> the resource when parsing the memory spaces in acpi_decode_space(),
>>> are we
>>> sure that's what we really want ?
>>>
>>> In DT, a host bridge range has a:
>>>
>>> - CPU physical address
>>> - PCI bus address
>>>
>>> We use that to compute the offset between primary bus (ie CPU physical
>>> address) and secondary bus (ie PCI bus address).
>>>
>>> The value ending up in the PCI resource struct (for memory space) is
>>> the CPU physical address, if you do not add the offset in
>>> acpi_decode_space
>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
>>> ACPI,
>>> am I wrong ?
>> Hi Lorenzo,
>>     I may have found the divergence between us about the design here. You
>> treat it as a one-stage translation but I treat it as a
>> two-stage translation as below:
>> stage 1: map(translate) per-PCI-domain IO port address[0, 16M) into
>> system global IO port address. Here system global IO port address is
>> ioport_resource[0, IO_SPACE_LIMIT).
>> stage 2: map system IO port address into system memory address.
>>
>> We need two objects of struct resource_win to support above two-stage
>> translation. One object, type of IORESOURCE_IO, is used to support
>> stage one, and it will also used to allocate IO port resources
>> for PCI devices. Another object, type of IORESOURCE_MMIO, is used
>> to allocate resource from iomem_resource and setup MMIO mapping
>> to actually access IO ports.
>>
>> For ARM64, it doesn't support multiple per-PCI-domain(bus local)
>> IO port address space yet, so stage one seems to be optional
>> becomes the offset between bus local IO port address and system
>> IO port address is always 0. But we still need two objects of
>> struct resource_win. The first object is
>>     {
>>         offset:0,
>>         start:AddressMinimum,
>>         end:AddressMaximum,
>>         flags:IORESOURCE_IO
>>     }
>> Here it's type of IORESOURCE_IO and offset must be zero because
>> pcibios_resource_to_bus() will access it translate system IO
>> port address into bus local IO port address. With my patch,
>> the struct resource_win object created by the ACPI core will
>> be reused for this.
>>
>> The second object is:
>>     {
>>         offset:Translation_Offset,
>>         start:AddressMinimum + Translation_Offset,
>>         end:AddressMaximum + Translation_Offset,
>>         flags:IORESOURCE_MMIO
>>     }
>> Arch code need to create the second struct resource_win object
>> and actually setup the MMIO mapping.
>>
>> But there's really another bug need to get fixed, funciton
>> acpi_dev_ioresource_flags() assumes bus local IO port address
>> space is size of 64K, which is wrong for IA64 and ARM64.
>>
> 
> So what would be the Translation_Offset meaning for two cases DWordIo
> (....,TypeTranslation) vs DWordIo (....,TypeStatic)? And why we did not
> use TypeTranslation for IA64 so far?

IA64 actually ignores the translation type flag and just assume it's
TypeTranslation, so there may be some IA64 BIOS implementations
accidentally using TypeStatic. That's why we parsing SparseTranslation
flag without checking TranslationType flag. I feel ARM64 may face the
same situation as IA64:(

We may expect (TypeStatic, 0-offset) and (TypeTranslation,
non-0-offset) in real word. For other two combinations, I haven't
found a real usage yet, though theoretically they are possible.

Thanks,
Gerry

> 
> I am worried that TypeTranslation fall into the IA64 category but ACPI
> tables were already written incorrectly.
> 
> Tomasz
> 
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-12 14:04                               ` Jiang Liu
@ 2015-11-12 14:45                                 ` Tomasz Nowicki
  2015-11-12 15:05                                   ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-12 14:45 UTC (permalink / raw)
  To: Jiang Liu, Lorenzo Pieralisi
  Cc: Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 12.11.2015 15:04, Jiang Liu wrote:
> On 2015/11/12 21:21, Tomasz Nowicki wrote:
>> On 12.11.2015 09:43, Jiang Liu wrote:
>>> On 2015/11/12 1:46, Lorenzo Pieralisi wrote:
>>>> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
>>>>
>>>> [...]
>>>>
>>>>>>> In particular, I would like to understand, for an eg DWordIO
>>>>>>> descriptor,
>>>>>>> what Range Minimum, Range Maximum and Translation Offset represent,
>>>>>>> they can't mean different things depending on the SW parsing them,
>>>>>>> this totally defeats the purpose.
>>>>>>
>>>>>> I have no clue about what those mean in ACPI though.
>>>>>>
>>>>>> Generally speaking, each PCI domain is expected to have a (normally
>>>>>> 64KB)
>>>>>> range of CPU addresses that gets translated into PCI I/O space the
>>>>>> same
>>>>>> way that config space and memory space are handled.
>>>>>> This is true for almost every architecture except for x86, which uses
>>>>>> different CPU instructions for I/O space compared to the other spaces.
>>>>>>
>>>>>>> By the way, ia64 ioremaps the translation_offset (ie new_space()), so
>>>>>>> basically that's the CPU physical address at which the PCI host
>>>>>>> bridge
>>>>>>> map the IO space transactions), I do not think ia64 is any
>>>>>>> different from
>>>>>>> arm64 in this respect, if it is please provide an HW description
>>>>>>> here from
>>>>>>> the PCI bus perspective here (also an example of ia64 ACPI PCI
>>>>>>> host bridge
>>>>>>> tables would help).
>>>>>>
>>>>>> The main difference between ia64 and a lot of the other
>>>>>> architectures (e.g.
>>>>>> sparc is different again) is that ia64 defines a logical address range
>>>>>> in terms of having a small number for each I/O space followed by the
>>>>>> offset within that space as a 'port number' and uses a mapping
>>>>>> function
>>>>>> that is defined as
>>>>>>
>>>>>> static inline void *__ia64_mk_io_addr (unsigned long port)
>>>>>> {
>>>>>>           struct io_space *space = &io_space[IO_SPACE_NR(port)];
>>>>>>           return (space->mmio_base | IO_SPACE_PORT(port););
>>>>>> }
>>>>>> static inline unsigned int inl(unsigned long port)
>>>>>> {
>>>>>>           return *__ia64_mk_io_addr(port);
>>>>>> }
>>>>>>
>>>>>> Most architectures allow only one I/O port range and put it at a fixed
>>>>>> virtual address so that inl() simply becomes
>>>>>>
>>>>>> static inline u32 inl(unsigned long addr)
>>>>>> {
>>>>>>           return readl(PCI_IOBASE + addr);
>>>>>> }
>>>>>>
>>>>>> which noticeably reduces code size.
>>>>>>
>>>>>> On some architectures (powerpc, arm, arm64), we then get the same
>>>>>> simplified
>>>>>> definition with a fixed virtual address, and use pci_ioremap_io() or
>>>>>> something like that to to map a physical address range into this
>>>>>> virtual
>>>>>> address window at the correct io_offset;
>>>>> Hi all,
>>>>>      Thanks for explanation, I found a way to make the ACPI resource
>>>>> parsing interface arch neutral, it should help to address Lorenzo's
>>>>> concern. Please refer to the attached patch. (It's still RFC, not
>>>>> tested
>>>>> yet).
>>>>
>>>> If we go with this approach though, you are not adding the offset to
>>>> the resource when parsing the memory spaces in acpi_decode_space(),
>>>> are we
>>>> sure that's what we really want ?
>>>>
>>>> In DT, a host bridge range has a:
>>>>
>>>> - CPU physical address
>>>> - PCI bus address
>>>>
>>>> We use that to compute the offset between primary bus (ie CPU physical
>>>> address) and secondary bus (ie PCI bus address).
>>>>
>>>> The value ending up in the PCI resource struct (for memory space) is
>>>> the CPU physical address, if you do not add the offset in
>>>> acpi_decode_space
>>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
>>>> ACPI,
>>>> am I wrong ?
>>> Hi Lorenzo,
>>>      I may have found the divergence between us about the design here. You
>>> treat it as a one-stage translation but I treat it as a
>>> two-stage translation as below:
>>> stage 1: map(translate) per-PCI-domain IO port address[0, 16M) into
>>> system global IO port address. Here system global IO port address is
>>> ioport_resource[0, IO_SPACE_LIMIT).
>>> stage 2: map system IO port address into system memory address.
>>>
>>> We need two objects of struct resource_win to support above two-stage
>>> translation. One object, type of IORESOURCE_IO, is used to support
>>> stage one, and it will also used to allocate IO port resources
>>> for PCI devices. Another object, type of IORESOURCE_MMIO, is used
>>> to allocate resource from iomem_resource and setup MMIO mapping
>>> to actually access IO ports.
>>>
>>> For ARM64, it doesn't support multiple per-PCI-domain(bus local)
>>> IO port address space yet, so stage one seems to be optional
>>> becomes the offset between bus local IO port address and system
>>> IO port address is always 0. But we still need two objects of
>>> struct resource_win. The first object is
>>>      {
>>>          offset:0,
>>>          start:AddressMinimum,
>>>          end:AddressMaximum,
>>>          flags:IORESOURCE_IO
>>>      }
>>> Here it's type of IORESOURCE_IO and offset must be zero because
>>> pcibios_resource_to_bus() will access it translate system IO
>>> port address into bus local IO port address. With my patch,
>>> the struct resource_win object created by the ACPI core will
>>> be reused for this.
>>>
>>> The second object is:
>>>      {
>>>          offset:Translation_Offset,
>>>          start:AddressMinimum + Translation_Offset,
>>>          end:AddressMaximum + Translation_Offset,
>>>          flags:IORESOURCE_MMIO
>>>      }
>>> Arch code need to create the second struct resource_win object
>>> and actually setup the MMIO mapping.
>>>
>>> But there's really another bug need to get fixed, funciton
>>> acpi_dev_ioresource_flags() assumes bus local IO port address
>>> space is size of 64K, which is wrong for IA64 and ARM64.
>>>
>>
>> So what would be the Translation_Offset meaning for two cases DWordIo
>> (....,TypeTranslation) vs DWordIo (....,TypeStatic)? And why we did not
>> use TypeTranslation for IA64 so far?
>
> IA64 actually ignores the translation type flag and just assume it's
> TypeTranslation, so there may be some IA64 BIOS implementations
> accidentally using TypeStatic. That's why we parsing SparseTranslation
> flag without checking TranslationType flag. I feel ARM64 may face the
> same situation as IA64:(
>
> We may expect (TypeStatic, 0-offset) and (TypeTranslation,
> non-0-offset) in real word. For other two combinations, I haven't
> found a real usage yet, though theoretically they are possible.
>

I think we should not bend the generic code for IA64 only and expose 
other platforms to the same issue. Instead, lets interpret spec 
correctly and create IA64 quirk for the sake of backward compatibility. 
Thoughts?

Regards,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-12 14:45                                 ` Tomasz Nowicki
@ 2015-11-12 15:05                                   ` Jiang Liu
  2015-11-13 12:57                                     ` Tomasz Nowicki
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-12 15:05 UTC (permalink / raw)
  To: Tomasz Nowicki, Lorenzo Pieralisi
  Cc: Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 2015/11/12 22:45, Tomasz Nowicki wrote:
> On 12.11.2015 15:04, Jiang Liu wrote:
>> On 2015/11/12 21:21, Tomasz Nowicki wrote:
>>> On 12.11.2015 09:43, Jiang Liu wrote:
>>>> On 2015/11/12 1:46, Lorenzo Pieralisi wrote:
>>>>> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
>>>>>
>>>>> [...]
>>>>>
>>>>>>>> In particular, I would like to understand, for an eg DWordIO
>>>>>>>> descriptor,
>>>>>>>> what Range Minimum, Range Maximum and Translation Offset represent,
>>>>>>>> they can't mean different things depending on the SW parsing them,
>>>>>>>> this totally defeats the purpose.
>>>>>>>
>>>>>>> I have no clue about what those mean in ACPI though.
>>>>>>>
>>>>>>> Generally speaking, each PCI domain is expected to have a (normally
>>>>>>> 64KB)
>>>>>>> range of CPU addresses that gets translated into PCI I/O space the
>>>>>>> same
>>>>>>> way that config space and memory space are handled.
>>>>>>> This is true for almost every architecture except for x86, which
>>>>>>> uses
>>>>>>> different CPU instructions for I/O space compared to the other
>>>>>>> spaces.
>>>>>>>
>>>>>>>> By the way, ia64 ioremaps the translation_offset (ie
>>>>>>>> new_space()), so
>>>>>>>> basically that's the CPU physical address at which the PCI host
>>>>>>>> bridge
>>>>>>>> map the IO space transactions), I do not think ia64 is any
>>>>>>>> different from
>>>>>>>> arm64 in this respect, if it is please provide an HW description
>>>>>>>> here from
>>>>>>>> the PCI bus perspective here (also an example of ia64 ACPI PCI
>>>>>>>> host bridge
>>>>>>>> tables would help).
>>>>>>>
>>>>>>> The main difference between ia64 and a lot of the other
>>>>>>> architectures (e.g.
>>>>>>> sparc is different again) is that ia64 defines a logical address
>>>>>>> range
>>>>>>> in terms of having a small number for each I/O space followed by the
>>>>>>> offset within that space as a 'port number' and uses a mapping
>>>>>>> function
>>>>>>> that is defined as
>>>>>>>
>>>>>>> static inline void *__ia64_mk_io_addr (unsigned long port)
>>>>>>> {
>>>>>>>           struct io_space *space = &io_space[IO_SPACE_NR(port)];
>>>>>>>           return (space->mmio_base | IO_SPACE_PORT(port););
>>>>>>> }
>>>>>>> static inline unsigned int inl(unsigned long port)
>>>>>>> {
>>>>>>>           return *__ia64_mk_io_addr(port);
>>>>>>> }
>>>>>>>
>>>>>>> Most architectures allow only one I/O port range and put it at a
>>>>>>> fixed
>>>>>>> virtual address so that inl() simply becomes
>>>>>>>
>>>>>>> static inline u32 inl(unsigned long addr)
>>>>>>> {
>>>>>>>           return readl(PCI_IOBASE + addr);
>>>>>>> }
>>>>>>>
>>>>>>> which noticeably reduces code size.
>>>>>>>
>>>>>>> On some architectures (powerpc, arm, arm64), we then get the same
>>>>>>> simplified
>>>>>>> definition with a fixed virtual address, and use pci_ioremap_io() or
>>>>>>> something like that to to map a physical address range into this
>>>>>>> virtual
>>>>>>> address window at the correct io_offset;
>>>>>> Hi all,
>>>>>>      Thanks for explanation, I found a way to make the ACPI resource
>>>>>> parsing interface arch neutral, it should help to address Lorenzo's
>>>>>> concern. Please refer to the attached patch. (It's still RFC, not
>>>>>> tested
>>>>>> yet).
>>>>>
>>>>> If we go with this approach though, you are not adding the offset to
>>>>> the resource when parsing the memory spaces in acpi_decode_space(),
>>>>> are we
>>>>> sure that's what we really want ?
>>>>>
>>>>> In DT, a host bridge range has a:
>>>>>
>>>>> - CPU physical address
>>>>> - PCI bus address
>>>>>
>>>>> We use that to compute the offset between primary bus (ie CPU physical
>>>>> address) and secondary bus (ie PCI bus address).
>>>>>
>>>>> The value ending up in the PCI resource struct (for memory space) is
>>>>> the CPU physical address, if you do not add the offset in
>>>>> acpi_decode_space
>>>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
>>>>> ACPI,
>>>>> am I wrong ?
>>>> Hi Lorenzo,
>>>>      I may have found the divergence between us about the design
>>>> here. You
>>>> treat it as a one-stage translation but I treat it as a
>>>> two-stage translation as below:
>>>> stage 1: map(translate) per-PCI-domain IO port address[0, 16M) into
>>>> system global IO port address. Here system global IO port address is
>>>> ioport_resource[0, IO_SPACE_LIMIT).
>>>> stage 2: map system IO port address into system memory address.
>>>>
>>>> We need two objects of struct resource_win to support above two-stage
>>>> translation. One object, type of IORESOURCE_IO, is used to support
>>>> stage one, and it will also used to allocate IO port resources
>>>> for PCI devices. Another object, type of IORESOURCE_MMIO, is used
>>>> to allocate resource from iomem_resource and setup MMIO mapping
>>>> to actually access IO ports.
>>>>
>>>> For ARM64, it doesn't support multiple per-PCI-domain(bus local)
>>>> IO port address space yet, so stage one seems to be optional
>>>> becomes the offset between bus local IO port address and system
>>>> IO port address is always 0. But we still need two objects of
>>>> struct resource_win. The first object is
>>>>      {
>>>>          offset:0,
>>>>          start:AddressMinimum,
>>>>          end:AddressMaximum,
>>>>          flags:IORESOURCE_IO
>>>>      }
>>>> Here it's type of IORESOURCE_IO and offset must be zero because
>>>> pcibios_resource_to_bus() will access it translate system IO
>>>> port address into bus local IO port address. With my patch,
>>>> the struct resource_win object created by the ACPI core will
>>>> be reused for this.
>>>>
>>>> The second object is:
>>>>      {
>>>>          offset:Translation_Offset,
>>>>          start:AddressMinimum + Translation_Offset,
>>>>          end:AddressMaximum + Translation_Offset,
>>>>          flags:IORESOURCE_MMIO
>>>>      }
>>>> Arch code need to create the second struct resource_win object
>>>> and actually setup the MMIO mapping.
>>>>
>>>> But there's really another bug need to get fixed, funciton
>>>> acpi_dev_ioresource_flags() assumes bus local IO port address
>>>> space is size of 64K, which is wrong for IA64 and ARM64.
>>>>
>>>
>>> So what would be the Translation_Offset meaning for two cases DWordIo
>>> (....,TypeTranslation) vs DWordIo (....,TypeStatic)? And why we did not
>>> use TypeTranslation for IA64 so far?
>>
>> IA64 actually ignores the translation type flag and just assume it's
>> TypeTranslation, so there may be some IA64 BIOS implementations
>> accidentally using TypeStatic. That's why we parsing SparseTranslation
>> flag without checking TranslationType flag. I feel ARM64 may face the
>> same situation as IA64:(
>>
>> We may expect (TypeStatic, 0-offset) and (TypeTranslation,
>> non-0-offset) in real word. For other two combinations, I haven't
>> found a real usage yet, though theoretically they are possible.
>>
> 
> I think we should not bend the generic code for IA64 only and expose
> other platforms to the same issue. Instead, lets interpret spec
> correctly and create IA64 quirk for the sake of backward compatibility.
> Thoughts?
I think there are at least two factors related to this issue.

First we still lack of a way/framework to fix errors in ACPI resource
descriptors. Recently we have refined ACPI resource parsing interfaces
and enforced strictly sanity check. This brings us some regressions
which are really BIOS flaws, but it used to work and now breaks:(
I'm still struggling to get those regressions fixed. So we may run
into the same situation if we enforce strict check for TranslationType:(

Second enforcing strict check doesn't bring us too much benifits.
Translation type is almost platform specific, and we haven't found a
platform support both TypeTranslation and TypeStatic, so arch code
may assume the correct translation type no matter what BIOS reports.
So it won't hurt us even BIOS reports wrong translation type.

So I'm tending to keep current implementation with looser checking,
otherwise it may cause regressions.
Thanks,
Gerry


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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-12 15:05                                   ` Jiang Liu
@ 2015-11-13 12:57                                     ` Tomasz Nowicki
  2015-11-13 17:03                                       ` Lorenzo Pieralisi
  0 siblings, 1 reply; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-13 12:57 UTC (permalink / raw)
  To: Jiang Liu, Lorenzo Pieralisi
  Cc: Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 12.11.2015 16:05, Jiang Liu wrote:
> On 2015/11/12 22:45, Tomasz Nowicki wrote:
>> On 12.11.2015 15:04, Jiang Liu wrote:
>>> On 2015/11/12 21:21, Tomasz Nowicki wrote:
>>>> On 12.11.2015 09:43, Jiang Liu wrote:
>>>>> On 2015/11/12 1:46, Lorenzo Pieralisi wrote:
>>>>>> On Tue, Nov 10, 2015 at 01:50:46PM +0800, Jiang Liu wrote:
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>>>> In particular, I would like to understand, for an eg DWordIO
>>>>>>>>> descriptor,
>>>>>>>>> what Range Minimum, Range Maximum and Translation Offset represent,
>>>>>>>>> they can't mean different things depending on the SW parsing them,
>>>>>>>>> this totally defeats the purpose.
>>>>>>>>
>>>>>>>> I have no clue about what those mean in ACPI though.
>>>>>>>>
>>>>>>>> Generally speaking, each PCI domain is expected to have a (normally
>>>>>>>> 64KB)
>>>>>>>> range of CPU addresses that gets translated into PCI I/O space the
>>>>>>>> same
>>>>>>>> way that config space and memory space are handled.
>>>>>>>> This is true for almost every architecture except for x86, which
>>>>>>>> uses
>>>>>>>> different CPU instructions for I/O space compared to the other
>>>>>>>> spaces.
>>>>>>>>
>>>>>>>>> By the way, ia64 ioremaps the translation_offset (ie
>>>>>>>>> new_space()), so
>>>>>>>>> basically that's the CPU physical address at which the PCI host
>>>>>>>>> bridge
>>>>>>>>> map the IO space transactions), I do not think ia64 is any
>>>>>>>>> different from
>>>>>>>>> arm64 in this respect, if it is please provide an HW description
>>>>>>>>> here from
>>>>>>>>> the PCI bus perspective here (also an example of ia64 ACPI PCI
>>>>>>>>> host bridge
>>>>>>>>> tables would help).
>>>>>>>>
>>>>>>>> The main difference between ia64 and a lot of the other
>>>>>>>> architectures (e.g.
>>>>>>>> sparc is different again) is that ia64 defines a logical address
>>>>>>>> range
>>>>>>>> in terms of having a small number for each I/O space followed by the
>>>>>>>> offset within that space as a 'port number' and uses a mapping
>>>>>>>> function
>>>>>>>> that is defined as
>>>>>>>>
>>>>>>>> static inline void *__ia64_mk_io_addr (unsigned long port)
>>>>>>>> {
>>>>>>>>            struct io_space *space = &io_space[IO_SPACE_NR(port)];
>>>>>>>>            return (space->mmio_base | IO_SPACE_PORT(port););
>>>>>>>> }
>>>>>>>> static inline unsigned int inl(unsigned long port)
>>>>>>>> {
>>>>>>>>            return *__ia64_mk_io_addr(port);
>>>>>>>> }
>>>>>>>>
>>>>>>>> Most architectures allow only one I/O port range and put it at a
>>>>>>>> fixed
>>>>>>>> virtual address so that inl() simply becomes
>>>>>>>>
>>>>>>>> static inline u32 inl(unsigned long addr)
>>>>>>>> {
>>>>>>>>            return readl(PCI_IOBASE + addr);
>>>>>>>> }
>>>>>>>>
>>>>>>>> which noticeably reduces code size.
>>>>>>>>
>>>>>>>> On some architectures (powerpc, arm, arm64), we then get the same
>>>>>>>> simplified
>>>>>>>> definition with a fixed virtual address, and use pci_ioremap_io() or
>>>>>>>> something like that to to map a physical address range into this
>>>>>>>> virtual
>>>>>>>> address window at the correct io_offset;
>>>>>>> Hi all,
>>>>>>>       Thanks for explanation, I found a way to make the ACPI resource
>>>>>>> parsing interface arch neutral, it should help to address Lorenzo's
>>>>>>> concern. Please refer to the attached patch. (It's still RFC, not
>>>>>>> tested
>>>>>>> yet).
>>>>>>
>>>>>> If we go with this approach though, you are not adding the offset to
>>>>>> the resource when parsing the memory spaces in acpi_decode_space(),
>>>>>> are we
>>>>>> sure that's what we really want ?
>>>>>>
>>>>>> In DT, a host bridge range has a:
>>>>>>
>>>>>> - CPU physical address
>>>>>> - PCI bus address
>>>>>>
>>>>>> We use that to compute the offset between primary bus (ie CPU physical
>>>>>> address) and secondary bus (ie PCI bus address).
>>>>>>
>>>>>> The value ending up in the PCI resource struct (for memory space) is
>>>>>> the CPU physical address, if you do not add the offset in
>>>>>> acpi_decode_space
>>>>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
>>>>>> ACPI,
>>>>>> am I wrong ?
>>>>> Hi Lorenzo,
>>>>>       I may have found the divergence between us about the design
>>>>> here. You
>>>>> treat it as a one-stage translation but I treat it as a
>>>>> two-stage translation as below:
>>>>> stage 1: map(translate) per-PCI-domain IO port address[0, 16M) into
>>>>> system global IO port address. Here system global IO port address is
>>>>> ioport_resource[0, IO_SPACE_LIMIT).
>>>>> stage 2: map system IO port address into system memory address.
>>>>>
>>>>> We need two objects of struct resource_win to support above two-stage
>>>>> translation. One object, type of IORESOURCE_IO, is used to support
>>>>> stage one, and it will also used to allocate IO port resources
>>>>> for PCI devices. Another object, type of IORESOURCE_MMIO, is used
>>>>> to allocate resource from iomem_resource and setup MMIO mapping
>>>>> to actually access IO ports.
>>>>>
>>>>> For ARM64, it doesn't support multiple per-PCI-domain(bus local)
>>>>> IO port address space yet, so stage one seems to be optional
>>>>> becomes the offset between bus local IO port address and system
>>>>> IO port address is always 0. But we still need two objects of
>>>>> struct resource_win. The first object is
>>>>>       {
>>>>>           offset:0,
>>>>>           start:AddressMinimum,
>>>>>           end:AddressMaximum,
>>>>>           flags:IORESOURCE_IO
>>>>>       }
>>>>> Here it's type of IORESOURCE_IO and offset must be zero because
>>>>> pcibios_resource_to_bus() will access it translate system IO
>>>>> port address into bus local IO port address. With my patch,
>>>>> the struct resource_win object created by the ACPI core will
>>>>> be reused for this.
>>>>>
>>>>> The second object is:
>>>>>       {
>>>>>           offset:Translation_Offset,
>>>>>           start:AddressMinimum + Translation_Offset,
>>>>>           end:AddressMaximum + Translation_Offset,
>>>>>           flags:IORESOURCE_MMIO
>>>>>       }
>>>>> Arch code need to create the second struct resource_win object
>>>>> and actually setup the MMIO mapping.
>>>>>
>>>>> But there's really another bug need to get fixed, funciton
>>>>> acpi_dev_ioresource_flags() assumes bus local IO port address
>>>>> space is size of 64K, which is wrong for IA64 and ARM64.
>>>>>
>>>>
>>>> So what would be the Translation_Offset meaning for two cases DWordIo
>>>> (....,TypeTranslation) vs DWordIo (....,TypeStatic)? And why we did not
>>>> use TypeTranslation for IA64 so far?
>>>
>>> IA64 actually ignores the translation type flag and just assume it's
>>> TypeTranslation, so there may be some IA64 BIOS implementations
>>> accidentally using TypeStatic. That's why we parsing SparseTranslation
>>> flag without checking TranslationType flag. I feel ARM64 may face the
>>> same situation as IA64:(
>>>
>>> We may expect (TypeStatic, 0-offset) and (TypeTranslation,
>>> non-0-offset) in real word. For other two combinations, I haven't
>>> found a real usage yet, though theoretically they are possible.
>>>
>>
>> I think we should not bend the generic code for IA64 only and expose
>> other platforms to the same issue. Instead, lets interpret spec
>> correctly and create IA64 quirk for the sake of backward compatibility.
>> Thoughts?
> I think there are at least two factors related to this issue.
>
> First we still lack of a way/framework to fix errors in ACPI resource
> descriptors. Recently we have refined ACPI resource parsing interfaces
> and enforced strictly sanity check. This brings us some regressions
> which are really BIOS flaws, but it used to work and now breaks:(
> I'm still struggling to get those regressions fixed. So we may run
> into the same situation if we enforce strict check for TranslationType:(
>
> Second enforcing strict check doesn't bring us too much benifits.
> Translation type is almost platform specific, and we haven't found a
> platform support both TypeTranslation and TypeStatic, so arch code
> may assume the correct translation type no matter what BIOS reports.
> So it won't hurt us even BIOS reports wrong translation type.
>

That is my point, lets pass down all we need from resource range 
descriptors to arch code, then archs with known quirks can whatever is 
needed to make it works. However, generic code like acpi_decode_space 
cannot play with offsets with silent IA64 assumption.

To sum it up, your last patch looks ok to me modulo Lorenzo's concern:
 >>>>>> If we go with this approach though, you are not adding the offset to
 >>>>>> the resource when parsing the memory spaces in acpi_decode_space(),
 >>>>>> are we
 >>>>>> sure that's what we really want ?
 >>>>>>
 >>>>>> In DT, a host bridge range has a:
 >>>>>>
 >>>>>> - CPU physical address
 >>>>>> - PCI bus address
 >>>>>>
 >>>>>> We use that to compute the offset between primary bus (ie CPU 
physical
 >>>>>> address) and secondary bus (ie PCI bus address).
 >>>>>>
 >>>>>> The value ending up in the PCI resource struct (for memory space) is
 >>>>>> the CPU physical address, if you do not add the offset in
 >>>>>> acpi_decode_space
 >>>>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
 >>>>>> ACPI,
 >>>>>> am I wrong ?
His concern is that your patch will cause:
acpi_pci_root_validate_resources(&device->dev, list,
				 IORESOURCE_MEM);
to fail now.

Regards,
Tomasz

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-13 12:57                                     ` Tomasz Nowicki
@ 2015-11-13 17:03                                       ` Lorenzo Pieralisi
  2015-11-13 17:49                                         ` Jiang Liu
  0 siblings, 1 reply; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-13 17:03 UTC (permalink / raw)
  To: Tomasz Nowicki
  Cc: Jiang Liu, Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

Please trim your emails, thanks.

On Fri, Nov 13, 2015 at 01:57:30PM +0100, Tomasz Nowicki wrote:
> On 12.11.2015 16:05, Jiang Liu wrote:

[...]

> >>>IA64 actually ignores the translation type flag and just assume it's
> >>>TypeTranslation, so there may be some IA64 BIOS implementations
> >>>accidentally using TypeStatic. That's why we parsing SparseTranslation
> >>>flag without checking TranslationType flag. I feel ARM64 may face the
> >>>same situation as IA64:(
> >>>
> >>>We may expect (TypeStatic, 0-offset) and (TypeTranslation,
> >>>non-0-offset) in real word. For other two combinations, I haven't
> >>>found a real usage yet, though theoretically they are possible.

I do not understand why (TypeStatic, non-0-offset) is not a valid
option. Aren't there any (x86) platforms with a CPU<->PCI _physical_
address space offset out there (I am talking about memory space) ?

> >>I think we should not bend the generic code for IA64 only and expose
> >>other platforms to the same issue. Instead, lets interpret spec
> >>correctly and create IA64 quirk for the sake of backward compatibility.
> >>Thoughts?
> >I think there are at least two factors related to this issue.
> >
> >First we still lack of a way/framework to fix errors in ACPI resource
> >descriptors. Recently we have refined ACPI resource parsing interfaces
> >and enforced strictly sanity check. This brings us some regressions
> >which are really BIOS flaws, but it used to work and now breaks:(
> >I'm still struggling to get those regressions fixed. So we may run
> >into the same situation if we enforce strict check for TranslationType:(
> >
> >Second enforcing strict check doesn't bring us too much benifits.
> >Translation type is almost platform specific, and we haven't found a
> >platform support both TypeTranslation and TypeStatic, so arch code
> >may assume the correct translation type no matter what BIOS reports.
> >So it won't hurt us even BIOS reports wrong translation type.

TBH I still do not understand what TranslationType actually means,
I will ask whoever added that to the specification to understand it.

> That is my point, lets pass down all we need from resource range
> descriptors to arch code, then archs with known quirks can whatever
> is needed to make it works. However, generic code like
> acpi_decode_space cannot play with offsets with silent IA64
> assumption.
> 
> To sum it up, your last patch looks ok to me modulo Lorenzo's concern:
> >>>>>> If we go with this approach though, you are not adding the offset to
> >>>>>> the resource when parsing the memory spaces in acpi_decode_space(),
> >>>>>> are we
> >>>>>> sure that's what we really want ?
> >>>>>>
> >>>>>> In DT, a host bridge range has a:
> >>>>>>
> >>>>>> - CPU physical address
> >>>>>> - PCI bus address
> >>>>>>
> >>>>>> We use that to compute the offset between primary bus (ie CPU
> physical
> >>>>>> address) and secondary bus (ie PCI bus address).
> >>>>>>
> >>>>>> The value ending up in the PCI resource struct (for memory space) is
> >>>>>> the CPU physical address, if you do not add the offset in
> >>>>>> acpi_decode_space
> >>>>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
> >>>>>> ACPI,
> >>>>>> am I wrong ?
> His concern is that your patch will cause:
> acpi_pci_root_validate_resources(&device->dev, list,
> 				 IORESOURCE_MEM);
> to fail now.

Not really. My concern is that there might be platforms out there with
an offset between the CPU and PCI physical address spaces, and if we
remove the offset value in acpi_decode_space we can break them,
because in the kernel struct resource data we have to have CPU physical
addresses, not PCI ones. If offset == 0, we are home and dry, I do not
understand why that's a given, which is what we would assume if Jiang's
patch is merged as-is unless I am mistaken.

Thanks,
Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-13 17:03                                       ` Lorenzo Pieralisi
@ 2015-11-13 17:49                                         ` Jiang Liu
  2015-11-20 10:18                                           ` Lorenzo Pieralisi
  0 siblings, 1 reply; 56+ messages in thread
From: Jiang Liu @ 2015-11-13 17:49 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Tomasz Nowicki
  Cc: Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 2015/11/14 1:03, Lorenzo Pieralisi wrote:
> Please trim your emails, thanks.
> 
> On Fri, Nov 13, 2015 at 01:57:30PM +0100, Tomasz Nowicki wrote:
>> On 12.11.2015 16:05, Jiang Liu wrote:
> 
> [...]
> 
>>>>> IA64 actually ignores the translation type flag and just assume it's
>>>>> TypeTranslation, so there may be some IA64 BIOS implementations
>>>>> accidentally using TypeStatic. That's why we parsing SparseTranslation
>>>>> flag without checking TranslationType flag. I feel ARM64 may face the
>>>>> same situation as IA64:(
>>>>>
>>>>> We may expect (TypeStatic, 0-offset) and (TypeTranslation,
>>>>> non-0-offset) in real word. For other two combinations, I haven't
>>>>> found a real usage yet, though theoretically they are possible.
> 
> I do not understand why (TypeStatic, non-0-offset) is not a valid
> option. Aren't there any (x86) platforms with a CPU<->PCI _physical_
> address space offset out there (I am talking about memory space) ?

It's possible, but we have found such a design yet. If we eventually
encounter such a case, we need to enhance x86 specific code to support
it.

> 
>>>> I think we should not bend the generic code for IA64 only and expose
>>>> other platforms to the same issue. Instead, lets interpret spec
>>>> correctly and create IA64 quirk for the sake of backward compatibility.
>>>> Thoughts?
>>> I think there are at least two factors related to this issue.
>>>
>>> First we still lack of a way/framework to fix errors in ACPI resource
>>> descriptors. Recently we have refined ACPI resource parsing interfaces
>>> and enforced strictly sanity check. This brings us some regressions
>>> which are really BIOS flaws, but it used to work and now breaks:(
>>> I'm still struggling to get those regressions fixed. So we may run
>>> into the same situation if we enforce strict check for TranslationType:(
>>>
>>> Second enforcing strict check doesn't bring us too much benifits.
>>> Translation type is almost platform specific, and we haven't found a
>>> platform support both TypeTranslation and TypeStatic, so arch code
>>> may assume the correct translation type no matter what BIOS reports.
>>> So it won't hurt us even BIOS reports wrong translation type.
> 
> TBH I still do not understand what TranslationType actually means,
> I will ask whoever added that to the specification to understand it.
> 
>> That is my point, lets pass down all we need from resource range
>> descriptors to arch code, then archs with known quirks can whatever
>> is needed to make it works. However, generic code like
>> acpi_decode_space cannot play with offsets with silent IA64
>> assumption.
>>
>> To sum it up, your last patch looks ok to me modulo Lorenzo's concern:
>>>>>>>> If we go with this approach though, you are not adding the offset to
>>>>>>>> the resource when parsing the memory spaces in acpi_decode_space(),
>>>>>>>> are we
>>>>>>>> sure that's what we really want ?
>>>>>>>>
>>>>>>>> In DT, a host bridge range has a:
>>>>>>>>
>>>>>>>> - CPU physical address
>>>>>>>> - PCI bus address
>>>>>>>>
>>>>>>>> We use that to compute the offset between primary bus (ie CPU
>> physical
>>>>>>>> address) and secondary bus (ie PCI bus address).
>>>>>>>>
>>>>>>>> The value ending up in the PCI resource struct (for memory space) is
>>>>>>>> the CPU physical address, if you do not add the offset in
>>>>>>>> acpi_decode_space
>>>>>>>> that does not hold true on platforms where CPU<->PCI offset != 0 on
>>>>>>>> ACPI,
>>>>>>>> am I wrong ?
>> His concern is that your patch will cause:
>> acpi_pci_root_validate_resources(&device->dev, list,
>> 				 IORESOURCE_MEM);
>> to fail now.
> 
> Not really. My concern is that there might be platforms out there with
> an offset between the CPU and PCI physical address spaces, and if we
> remove the offset value in acpi_decode_space we can break them,
> because in the kernel struct resource data we have to have CPU physical
> addresses, not PCI ones. If offset == 0, we are home and dry, I do not
> understand why that's a given, which is what we would assume if Jiang's
> patch is merged as-is unless I am mistaken.
We try to exclude offset from struct resource in generic ACPI code,
and it's the arch's responsibility to decide how to manipulate struct
resource object if offset is not zero.

Currently offset is always zero for x86, and IA64 has arch specific
code to handle non-zero offset. So we should be safe without breaking
existing code. For ARM64, it's a little different from IA64 so it's
hard to share code between IA64 and ARM64.

> 
> Thanks,
> Lorenzo
> 

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-13 17:49                                         ` Jiang Liu
@ 2015-11-20 10:18                                           ` Lorenzo Pieralisi
  2015-11-27  6:59                                             ` Tomasz Nowicki
  0 siblings, 1 reply; 56+ messages in thread
From: Lorenzo Pieralisi @ 2015-11-20 10:18 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Tomasz Nowicki, Arnd Bergmann, Bjorn Helgaas, Rafael J . Wysocki,
	Marc Zyngier, Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci,
	linux-kernel, x86

Hi Jiang,

On Sat, Nov 14, 2015 at 01:49:08AM +0800, Jiang Liu wrote:

[...]

> > Not really. My concern is that there might be platforms out there with
> > an offset between the CPU and PCI physical address spaces, and if we
> > remove the offset value in acpi_decode_space we can break them,
> > because in the kernel struct resource data we have to have CPU physical
> > addresses, not PCI ones. If offset == 0, we are home and dry, I do not
> > understand why that's a given, which is what we would assume if Jiang's
> > patch is merged as-is unless I am mistaken.
> We try to exclude offset from struct resource in generic ACPI code,
> and it's the arch's responsibility to decide how to manipulate struct
> resource object if offset is not zero.
> 
> Currently offset is always zero for x86, and IA64 has arch specific
> code to handle non-zero offset. So we should be safe without breaking
> existing code. For ARM64, it's a little different from IA64 so it's
> hard to share code between IA64 and ARM64.

Can you drop the patch on the mailing lists please, we actually need it
to get ACPI ARM64 PCIe support in the kernel, please let me know how
you want to handle this and if you need any help.

Thanks,
Lorenzo

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-06 15:44                     ` Jiang Liu
@ 2015-11-23 15:23                       ` Sinan Kaya
  0 siblings, 0 replies; 56+ messages in thread
From: Sinan Kaya @ 2015-11-23 15:23 UTC (permalink / raw)
  To: Jiang Liu, Lorenzo Pieralisi
  Cc: Tomasz Nowicki, Bjorn Helgaas, Rafael J . Wysocki, Marc Zyngier,
	Hanjun Guo, Liviu Dudau, linux-acpi, linux-pci, linux-kernel,
	x86

On 11/6/2015 10:44 AM, Jiang Liu wrote:
> On 2015/11/6 23:32, Jiang Liu wrote:
>> On 2015/11/6 22:45, Lorenzo Pieralisi wrote:
>>> On Fri, Nov 06, 2015 at 09:22:46PM +0800, Jiang Liu wrote:
>>>> On 2015/11/6 20:40, Tomasz Nowicki wrote:
>>>>> On 06.11.2015 12:46, Jiang Liu wrote:
>>>>>> On 2015/11/6 18:37, Tomasz Nowicki wrote:
>>>>>>> On 06.11.2015 09:52, Jiang Liu wrote:
>>>>>>> Sure, ARM64 (0-16M IO space) QEMU example:
>>>>>>> DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
>>>>>>>           0x00000000,         // Granularity
>>>>>>>           0x00000000,         // Range Minimum
>>>>>>>           0x0000FFFF,         // Range Maximum
>>>>>>>           0x3EFF0000,         // Translation Offset
>>>>>>>           0x00010000,         // Length
>>>>>>>           ,, , TypeStatic)
>>>>>> The above DWordIO resource descriptor doesn't confirm to the ACPI spec.
>>>>>> According to my understanding, ARM/ARM64 has no concept of IO port
>>>>>> address space, so the PCI host bridge will map IO port on PCI side
>>>>>> onto MMIO on host side. In other words, PCI host bridge on ARM64
>>>>>> implement a IO Port->MMIO translation instead of a IO Port->IO Port
>>>>>> translation. If that's true, it should use 'TypeTranslation' instead
>>>>>> of 'TypeStatic'. And kernel ACPI resource parsing interface doesn't
>>>>>> support 'TypeTranslation' yet, so we need to find a solution for it.
>>>>>
>>>>> I think you are right, we need TypeTranslation flag for ARM64 DWordIO
>>>>> descriptors and an extra kernel patch to support it.
>>>> How about the attached to patch to support TypeTranslation?
>>>> It only passes compilation:)
>>>
>>> Eh, hopefully there are not any ACPI tables out there with that bit
>>> set that work _today_ and would not work with the patch attached :)
>>>
>>> My question is still there: do we want to handle the same problem
>>> as ia64 has in a different manner ? Certainly we won't be able
>>> to update ia64 platforms ACPI tables, so we would end up with
>>> two platforms handling IO resources in different ways unless I am
>>> missing something here.
>> There are some difference between IA64 and ARM64.
>> On IA64, it supports 16M IO address space per PCI domain and 256 PCI
>> domains at max. So the system IO address space is 16M * 256 = 4G.
>> So it does two level translations to support IO port
>> 1) translate PCI bus local IO port address into system global IO port
>>    address by adding acpi_des->translation_offset.
>> 2) translate the 4G system IO port address space into MMIO address.
>>    IA64 has reserved a 4G space for IO port mapping. This translation
>>    is done by arch specific method.
>> In other word, IA64 needs two level translation, but ACPI only provides
>> on (trans_type, trans_offset) pair for encoding, so it's used for step 1).
>>
>> For ARM64, I think currently it only needs step 2).
>>
>>>
>>> BTW, why would we add offset to res->start only if TypeTranslation is
>>> clear ? Is not that something we would do just to make things "work" ?
>>> That flag has no bearing on the offset, only on the resource type AFAIK.
>> It's not a hack, but a way to interpret ACPI spec:)
>>
>> With current linux resource management framework, we need to allocate
>> both MMIO and IO port address space range for an ACPI resource of type
>> 'TypeTranslation'. And struct resource could be either IO port or MMIO,
>> not both. So the choice is to keep the resource as IO port, and let
>> arch code to build the special MMIO mapping for it. Otherwise it will
>> break too many things if we convert the resource as MMIO.
>>
>> That said, we need to add translation_offset to convert bus local
>> IO port address into system global IO port address if it's type of
>> TypeStatic, because ioresource_ioport uses system global IO port
>> address.
>>
>> For an ACPI resource of type TypeTranslation, system global IO port
>> address equals bus local IO port address, and the translation_offset
>> is used to translate IO port address into MMIO address, so we shouldn't
>> add translation_offset to the IO port resource descriptor.
> One note for the TypeTranslation case, the arch code needs to reset
> resource_win->offset to zero after setting up the MMIO map. Sample
> code as below:
> va = ioremap(resource_win->offset + res->start, resource_size(res));
> resource_win->offset = 0;
> 
> Otherwise it will break pcibios_resource_to_bus() etc.
> 
>>
>> Thanks,
>> Gerry
>>
>>>
>>> This without taking into account ARM64 systems shipping with ACPI
>>> tables that does not set the TypeTranslation at present.
>>>
>>> On top of that, I noticed that core ACPI code handles Sparse
>>> Translation (ie _TRS), that should be considered meaningful only if _TTP
>>> is set (and that's not checked).
>> Yes, that's a flaw:(
>>
>>>
>>> Thoughts ?
>>>
>>> Thanks,
>>> Lorenzo
>>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Tomasz, Lorenzo;
I have an ARMv8 platform with IO address support where I can test this
implementation. Let me know if there is any patch that I can try.
Sinan


-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
Linux Foundation Collaborative Project

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

* Re: [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create()
  2015-11-20 10:18                                           ` Lorenzo Pieralisi
@ 2015-11-27  6:59                                             ` Tomasz Nowicki
  0 siblings, 0 replies; 56+ messages in thread
From: Tomasz Nowicki @ 2015-11-27  6:59 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Lorenzo Pieralisi, Arnd Bergmann, Bjorn Helgaas,
	Rafael J . Wysocki, Marc Zyngier, Hanjun Guo, Liviu Dudau,
	linux-acpi, linux-pci, linux-kernel, x86

On 20.11.2015 11:18, Lorenzo Pieralisi wrote:
> Hi Jiang,
>
> On Sat, Nov 14, 2015 at 01:49:08AM +0800, Jiang Liu wrote:
>
> [...]
>
>>> Not really. My concern is that there might be platforms out there with
>>> an offset between the CPU and PCI physical address spaces, and if we
>>> remove the offset value in acpi_decode_space we can break them,
>>> because in the kernel struct resource data we have to have CPU physical
>>> addresses, not PCI ones. If offset == 0, we are home and dry, I do not
>>> understand why that's a given, which is what we would assume if Jiang's
>>> patch is merged as-is unless I am mistaken.
>> We try to exclude offset from struct resource in generic ACPI code,
>> and it's the arch's responsibility to decide how to manipulate struct
>> resource object if offset is not zero.
>>
>> Currently offset is always zero for x86, and IA64 has arch specific
>> code to handle non-zero offset. So we should be safe without breaking
>> existing code. For ARM64, it's a little different from IA64 so it's
>> hard to share code between IA64 and ARM64.
>
> Can you drop the patch on the mailing lists please, we actually need it
> to get ACPI ARM64 PCIe support in the kernel, please let me know how
> you want to handle this and if you need any help.
>

Kindly reminder.

Regards,
Tomasz

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

end of thread, other threads:[~2015-11-27  7:01 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-14  6:29 [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Jiang Liu
2015-10-14  6:29 ` [Patch v7 1/7] ACPI/PCI: Enhance ACPI core to support sparse IO space Jiang Liu
2015-10-14  6:29 ` [Patch v7 2/7] ia64/PCI/ACPI: Use common ACPI resource parsing interface for host bridge Jiang Liu
2015-10-14  6:29 ` [Patch v7 3/7] ia64/PCI: Use common struct resource_entry to replace struct iospace_resource Jiang Liu
2015-10-14  6:29 ` [Patch v7 4/7] PCI/ACPI: Add interface acpi_pci_root_create() Jiang Liu
2015-10-15 20:47   ` Bjorn Helgaas
2015-10-21  9:57   ` Tomasz Nowicki
2015-10-21 11:02     ` Liviu Dudau
2015-10-21 11:27       ` Tomasz Nowicki
2015-10-21 11:42         ` Lorenzo Pieralisi
2015-10-21 12:16           ` Tomasz Nowicki
2015-10-21 11:48         ` Liviu Dudau
2015-10-21 11:49         ` Jiang Liu
2015-10-21 11:52           ` Liviu Dudau
2015-10-21 11:52             ` Liviu Dudau
2015-11-05 14:21   ` Tomasz Nowicki
2015-11-05 18:19     ` Lorenzo Pieralisi
2015-11-06  7:55       ` Jiang Liu
2015-11-06  8:52       ` Jiang Liu
2015-11-06 10:37         ` Tomasz Nowicki
2015-11-06 11:46           ` Jiang Liu
2015-11-06 12:40             ` Tomasz Nowicki
2015-11-06 13:22               ` Jiang Liu
2015-11-06 14:45                 ` Lorenzo Pieralisi
2015-11-06 15:32                   ` Jiang Liu
2015-11-06 15:44                     ` Jiang Liu
2015-11-23 15:23                       ` Sinan Kaya
2015-11-09 14:07                 ` Tomasz Nowicki
2015-11-09 17:10                   ` Lorenzo Pieralisi
2015-11-09 20:09                     ` Arnd Bergmann
2015-11-10  5:50                       ` Jiang Liu
2015-11-11 17:46                         ` Lorenzo Pieralisi
2015-11-11 18:12                           ` Liviu Dudau
2015-11-11 18:12                             ` Liviu Dudau
2015-11-11 20:55                           ` Arnd Bergmann
2015-11-12 12:08                             ` Lorenzo Pieralisi
2015-11-12  8:43                           ` Jiang Liu
2015-11-12 13:21                             ` Tomasz Nowicki
2015-11-12 14:04                               ` Jiang Liu
2015-11-12 14:45                                 ` Tomasz Nowicki
2015-11-12 15:05                                   ` Jiang Liu
2015-11-13 12:57                                     ` Tomasz Nowicki
2015-11-13 17:03                                       ` Lorenzo Pieralisi
2015-11-13 17:49                                         ` Jiang Liu
2015-11-20 10:18                                           ` Lorenzo Pieralisi
2015-11-27  6:59                                             ` Tomasz Nowicki
2015-11-06 12:51         ` Lorenzo Pieralisi
2015-11-06 10:18       ` Tomasz Nowicki
2015-11-06  7:51     ` Jiang Liu
2015-10-14  6:29 ` [Patch v7 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
2015-10-14  6:29 ` [Patch v7 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
2015-10-15 20:46   ` Bjorn Helgaas
2015-10-14  6:29 ` [Patch v7 7/7] ia64/PCI/ACPI: " Jiang Liu
2015-10-15 20:48 ` [Patch v7 0/7] Consolidate ACPI PCI root common code into ACPI core Bjorn Helgaas
2015-10-15 21:49   ` Rafael J. Wysocki
2015-10-16  1:56     ` Jiang Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.