* [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
[not found] <1442218057-4355-1-git-send-email-jiang.liu@linux.intel.com>
@ 2015-09-14 8:07 ` Jiang Liu
2015-10-06 17:47 ` Bjorn Helgaas
2015-09-14 8:07 ` [Patch v6 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
2015-09-14 8:07 ` [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
2 siblings, 1 reply; 11+ messages in thread
From: Jiang Liu @ 2015-09-14 8:07 UTC (permalink / raw)
To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Rafael J. Wysocki,
Len Brown
Cc: Jiang Liu, linux-acpi, linux-kernel, x86, linux-pci
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>
---
drivers/acpi/pci_root.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci-acpi.h | 23 ++++++
2 files changed, 227 insertions(+)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 393706a5261b..48d27bd35b58 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);
+ }
+}
+
+static int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
+{
+ int ret;
+ struct list_head *list = &info->resources;
+ struct acpi_device *device = info->bridge;
+ struct resource_entry *entry, *tmp;
+ unsigned long flags;
+
+ flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
+ ret = acpi_dev_get_resources(device, list,
+ acpi_dev_filter_resource_type_cb,
+ (void *)flags);
+ if (ret < 0)
+ dev_warn(&device->dev,
+ "failed to parse _CRS method, error code %d\n", ret);
+ else if (ret == 0)
+ dev_dbg(&device->dev,
+ "no IO and memory resources present in _CRS\n");
+ else {
+ resource_list_for_each_entry_safe(entry, tmp, list) {
+ if (entry->res->flags & IORESOURCE_DISABLED)
+ resource_list_destroy_entry(entry);
+ else
+ entry->res->name = info->name;
+ }
+ acpi_pci_root_validate_resources(&device->dev, list,
+ IORESOURCE_MEM);
+ acpi_pci_root_validate_resources(&device->dev, list,
+ IORESOURCE_IO);
+ }
+
+ return ret;
+}
+
+static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
+{
+ struct resource_entry *entry, *tmp;
+ struct resource *res, *conflict, *root = NULL;
+
+ resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
+ res = entry->res;
+ if (res->flags & IORESOURCE_MEM)
+ root = &iomem_resource;
+ else if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ else
+ continue;
+
+ conflict = insert_resource_conflict(root, res);
+ if (conflict) {
+ dev_info(&info->bridge->dev,
+ "ignoring host bridge window %pR (conflicts with %s %pR)\n",
+ res, conflict->name, conflict);
+ resource_list_destroy_entry(entry);
+ }
+ }
+}
+
+static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
+{
+ struct resource *res;
+ struct resource_entry *entry, *tmp;
+
+ if (!info)
+ return;
+
+ resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
+ res = entry->res;
+ if (res->parent &&
+ (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ release_resource(res);
+ resource_list_destroy_entry(entry);
+ }
+
+ info->ops->release_info(info);
+}
+
+static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
+{
+ struct resource *res;
+ struct resource_entry *entry;
+
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ res = entry->res;
+ if (res->parent &&
+ (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
+ release_resource(res);
+ }
+ __acpi_pci_root_release_info(bridge->release_data);
+}
+
+struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+ struct acpi_pci_root_ops *ops,
+ struct acpi_pci_root_info *info,
+ 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;
+ ret = acpi_pci_probe_root_resources(info);
+ if (ops->prepare_resources)
+ ret = ops->prepare_resources(info, ret);
+ if (ret < 0)
+ goto out_release_info;
+ else if (ret > 0)
+ pci_acpi_root_add_resources(info);
+ pci_add_resource(&info->resources, &root->secondary);
+
+ bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
+ sysdata, &info->resources);
+ if (bus) {
+ pci_scan_child_bus(bus);
+ pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
+ acpi_pci_root_release_info, info);
+ if (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..583af37c6030 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -52,6 +52,29 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
return ACPI_HANDLE(dev);
}
+struct acpi_pci_root;
+struct acpi_pci_root_ops;
+
+struct acpi_pci_root_info {
+ struct acpi_pci_root *root;
+ struct acpi_device *bridge;
+ struct acpi_pci_root_ops *ops;
+ struct list_head resources;
+ char name[16];
+};
+
+struct acpi_pci_root_ops {
+ struct pci_ops *pci_ops;
+ int (*init_info)(struct acpi_pci_root_info *info);
+ void (*release_info)(struct acpi_pci_root_info *info);
+ int (*prepare_resources)(struct acpi_pci_root_info *info, int status);
+};
+
+extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
+ struct acpi_pci_root_ops *ops,
+ struct acpi_pci_root_info *info,
+ void *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] 11+ messages in thread
* [Patch v6 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set
[not found] <1442218057-4355-1-git-send-email-jiang.liu@linux.intel.com>
2015-09-14 8:07 ` [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
@ 2015-09-14 8:07 ` Jiang Liu
2015-10-06 17:54 ` Bjorn Helgaas
2015-09-14 8:07 ` [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
2 siblings, 1 reply; 11+ messages in thread
From: Jiang Liu @ 2015-09-14 8:07 UTC (permalink / raw)
To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, x86
Cc: Jiang Liu, linux-acpi, linux-kernel, linux-pci
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.
Signed-off-by: Jiang Liu <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] 11+ messages in thread
* [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
[not found] <1442218057-4355-1-git-send-email-jiang.liu@linux.intel.com>
2015-09-14 8:07 ` [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
2015-09-14 8:07 ` [Patch v6 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
@ 2015-09-14 8:07 ` Jiang Liu
2015-10-06 18:01 ` Bjorn Helgaas
2 siblings, 1 reply; 11+ messages in thread
From: Jiang Liu @ 2015-09-14 8:07 UTC (permalink / raw)
To: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, x86
Cc: Jiang Liu, linux-acpi, linux-kernel, linux-pci
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>
---
arch/x86/pci/acpi.c | 293 +++++++++++++++------------------------------------
1 file changed, 86 insertions(+), 207 deletions(-)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5bc018559cc4..54bcca55b667 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,43 @@ static bool resource_is_pcicfg_ioport(struct resource *res)
res->start == 0xCF8 && res->end == 0xCFF;
}
-static void probe_pci_root_info(struct pci_root_info *info,
- struct acpi_device *device,
- int busnum, int domain,
- struct list_head *list)
+static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci,
+ int status)
{
- int ret;
+ struct acpi_device *device = ci->bridge;
+ int busnum = ci->root->secondary.start;
struct resource_entry *entry, *tmp;
- sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
- info->bridge = device;
- ret = acpi_dev_get_resources(device, list,
- acpi_dev_filter_resource_type_cb,
- (void *)(IORESOURCE_IO | IORESOURCE_MEM));
- if (ret < 0)
- dev_warn(&device->dev,
- "failed to parse _CRS method, error code %d\n", ret);
- else if (ret == 0)
- dev_dbg(&device->dev,
- "no IO and memory resources present in _CRS\n");
- else
- resource_list_for_each_entry_safe(entry, tmp, list) {
- if ((entry->res->flags & IORESOURCE_DISABLED) ||
- resource_is_pcicfg_ioport(entry->res))
+ if (pci_use_crs) {
+ resource_list_for_each_entry_safe(entry, tmp, &ci->resources)
+ if (resource_is_pcicfg_ioport(entry->res))
resource_list_destroy_entry(entry);
- else
- entry->res->name = info->name;
- }
+ return status;
+ }
+
+ resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
+ dev_printk(KERN_DEBUG, &device->dev,
+ "host bridge window %pR (ignored)\n", entry->res);
+ resource_list_destroy_entry(entry);
+ }
+ x86_pci_root_bus_resources(busnum, &ci->resources);
+
+ return 0;
}
+static struct acpi_pci_root_ops acpi_pci_root_ops = {
+ .pci_ops = &pci_root_ops,
+ .init_info = pci_acpi_root_init_info,
+ .release_info = pci_acpi_root_release_info,
+ .prepare_resources = pci_acpi_root_prepare_resources,
+};
+
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
- struct acpi_device *device = root->device;
- struct pci_root_info *info;
int domain = root->segment;
int busnum = root->secondary.start;
- struct resource_entry *res_entry;
- LIST_HEAD(crs_res);
- LIST_HEAD(resources);
+ int node = pci_acpi_root_get_node(root);
struct pci_bus *bus;
- struct pci_sysdata *sd;
- int node;
if (pci_ignore_seg)
root->segment = domain = 0;
@@ -410,71 +330,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 +369,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] 11+ messages in thread
* Re: [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
2015-09-14 8:07 ` [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
@ 2015-10-06 17:47 ` Bjorn Helgaas
2015-10-08 5:32 ` Jiang Liu
0 siblings, 1 reply; 11+ messages in thread
From: Bjorn Helgaas @ 2015-10-06 17:47 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Rafael J. Wysocki,
Len Brown, linux-acpi, linux-kernel, x86, linux-pci
Hi Jiang,
Strictly speaking, this patch by itself doesn't actually "consolidate"
anything because it only adds acpi_pci_root_create() (which isn't called by
anything yet), but doesn't remove the original x86 copy.
On Mon, Sep 14, 2015 at 04:07:33PM +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>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Some minor structuring comments below, but my ack is valid even if you
don't address them.
> ---
> drivers/acpi/pci_root.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pci-acpi.h | 23 ++++++
> 2 files changed, 227 insertions(+)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 393706a5261b..48d27bd35b58 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);
> + }
> +}
> +
> +static int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
> +{
> + int ret;
> + struct list_head *list = &info->resources;
> + struct acpi_device *device = info->bridge;
> + struct resource_entry *entry, *tmp;
> + unsigned long flags;
> +
> + flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
> + ret = acpi_dev_get_resources(device, list,
> + acpi_dev_filter_resource_type_cb,
> + (void *)flags);
> + if (ret < 0)
> + dev_warn(&device->dev,
> + "failed to parse _CRS method, error code %d\n", ret);
> + else if (ret == 0)
> + dev_dbg(&device->dev,
> + "no IO and memory resources present in _CRS\n");
> + else {
> + resource_list_for_each_entry_safe(entry, tmp, list) {
> + if (entry->res->flags & IORESOURCE_DISABLED)
> + resource_list_destroy_entry(entry);
> + else
> + entry->res->name = info->name;
> + }
> + acpi_pci_root_validate_resources(&device->dev, list,
> + IORESOURCE_MEM);
> + acpi_pci_root_validate_resources(&device->dev, list,
> + IORESOURCE_IO);
> + }
> +
> + return ret;
> +}
> +
> +static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
> +{
> + struct resource_entry *entry, *tmp;
> + struct resource *res, *conflict, *root = NULL;
> +
> + resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
> + res = entry->res;
> + if (res->flags & IORESOURCE_MEM)
> + root = &iomem_resource;
> + else if (res->flags & IORESOURCE_IO)
> + root = &ioport_resource;
> + else
> + continue;
> +
> + conflict = insert_resource_conflict(root, res);
> + if (conflict) {
> + dev_info(&info->bridge->dev,
> + "ignoring host bridge window %pR (conflicts with %s %pR)\n",
> + res, conflict->name, conflict);
> + resource_list_destroy_entry(entry);
> + }
> + }
> +}
> +
> +static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
> +{
> + struct resource *res;
> + struct resource_entry *entry, *tmp;
> +
> + if (!info)
> + return;
> +
> + resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
> + res = entry->res;
> + if (res->parent &&
> + (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
> + release_resource(res);
> + resource_list_destroy_entry(entry);
> + }
> +
> + info->ops->release_info(info);
> +}
> +
> +static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
> +{
> + struct resource *res;
> + struct resource_entry *entry;
> +
> + resource_list_for_each_entry(entry, &bridge->windows) {
> + res = entry->res;
> + if (res->parent &&
> + (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
> + release_resource(res);
> + }
> + __acpi_pci_root_release_info(bridge->release_data);
> +}
> +
> +struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
> + struct acpi_pci_root_ops *ops,
> + struct acpi_pci_root_info *info,
> + 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;
> + ret = acpi_pci_probe_root_resources(info);
> + if (ops->prepare_resources)
> + ret = ops->prepare_resources(info, ret);
> + if (ret < 0)
> + goto out_release_info;
> + else if (ret > 0)
> + pci_acpi_root_add_resources(info);
This is unnecessarily complicated: you set "ret", then overwrite it if
ops->prepare_resources. By the time you test "ret", it's messy to
figure out what it means.
Both ops->prepare_resources() and pci_acpi_root_add_resources()
should be able to deal with empty resource lists, so can you do the
following instead?
ret = acpi_pci_probe_root_resources(info);
if (ret < 0)
goto out_release_info;
if (ops->prepare_resources) {
ret = ops->prepare_resources(info, ret);
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) {
if (!bus)
goto out_release_info;
Then it looks like the other error paths above, and you can un-indent
the following code, which is the normal path:
> + 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..583af37c6030 100644
> --- a/include/linux/pci-acpi.h
> +++ b/include/linux/pci-acpi.h
> @@ -52,6 +52,29 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
> return ACPI_HANDLE(dev);
> }
>
> +struct acpi_pci_root;
> +struct acpi_pci_root_ops;
> +
> +struct acpi_pci_root_info {
> + struct acpi_pci_root *root;
> + struct acpi_device *bridge;
> + struct acpi_pci_root_ops *ops;
> + struct list_head resources;
> + char name[16];
> +};
> +
> +struct acpi_pci_root_ops {
> + struct pci_ops *pci_ops;
> + int (*init_info)(struct acpi_pci_root_info *info);
> + void (*release_info)(struct acpi_pci_root_info *info);
> + int (*prepare_resources)(struct acpi_pci_root_info *info, int status);
> +};
> +
> +extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
> + struct acpi_pci_root_ops *ops,
> + struct acpi_pci_root_info *info,
> + void *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-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] 11+ messages in thread
* Re: [Patch v6 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set
2015-09-14 8:07 ` [Patch v6 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
@ 2015-10-06 17:54 ` Bjorn Helgaas
0 siblings, 0 replies; 11+ messages in thread
From: Bjorn Helgaas @ 2015-10-06 17:54 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, x86, linux-acpi, linux-kernel,
linux-pci
On Mon, Sep 14, 2015 at 04:07:34PM +0800, Jiang Liu wrote:
> 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.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.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
>
> --
> 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] 11+ messages in thread
* Re: [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
2015-09-14 8:07 ` [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
@ 2015-10-06 18:01 ` Bjorn Helgaas
2015-10-07 8:52 ` Hanjun Guo
0 siblings, 1 reply; 11+ messages in thread
From: Bjorn Helgaas @ 2015-10-06 18:01 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, x86, linux-acpi, linux-kernel,
linux-pci
On Mon, Sep 14, 2015 at 04:07:35PM +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>
Is there a corresponding ia64 patch? If we're really consolidating
this code (which I completely support), we need to do the whole job.
> ---
> arch/x86/pci/acpi.c | 293 +++++++++++++++------------------------------------
> 1 file changed, 86 insertions(+), 207 deletions(-)
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
2015-10-06 18:01 ` Bjorn Helgaas
@ 2015-10-07 8:52 ` Hanjun Guo
2015-10-07 12:45 ` Bjorn Helgaas
0 siblings, 1 reply; 11+ messages in thread
From: Hanjun Guo @ 2015-10-07 8:52 UTC (permalink / raw)
To: Bjorn Helgaas, Jiang Liu
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Liviu Dudau, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, x86, linux-acpi, linux-kernel, linux-pci
On 10/07/2015 02:01 AM, Bjorn Helgaas wrote:
> On Mon, Sep 14, 2015 at 04:07:35PM +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>
>
> Is there a corresponding ia64 patch? If we're really consolidating
> this code (which I completely support), we need to do the whole job.
Yes, there is a patch for it:
[Patch v6 7/7] ia64/PCI/ACPI: Use common interface to support PCI host
bridge
which has lots of code simplification [1],
arch/ia64/pci/pci.c | 232
++++++++++-----------------------------------------
1 file changed, 46 insertions(+), 186 deletions(-)
[1]: https://lkml.org/lkml/2015/9/14/84
Thanks
Hanjun
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge
2015-10-07 8:52 ` Hanjun Guo
@ 2015-10-07 12:45 ` Bjorn Helgaas
0 siblings, 0 replies; 11+ messages in thread
From: Bjorn Helgaas @ 2015-10-07 12:45 UTC (permalink / raw)
To: Hanjun Guo
Cc: Jiang Liu, Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Liviu Dudau, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, x86, linux-acpi, linux-kernel, linux-pci
On Wed, Oct 07, 2015 at 04:52:55PM +0800, Hanjun Guo wrote:
> On 10/07/2015 02:01 AM, Bjorn Helgaas wrote:
> >On Mon, Sep 14, 2015 at 04:07:35PM +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>
> >
> >Is there a corresponding ia64 patch? If we're really consolidating
> >this code (which I completely support), we need to do the whole job.
>
> Yes, there is a patch for it:
>
> [Patch v6 7/7] ia64/PCI/ACPI: Use common interface to support PCI
> host bridge
>
> which has lots of code simplification [1],
>
> arch/ia64/pci/pci.c | 232
> ++++++++++-----------------------------------------
> 1 file changed, 46 insertions(+), 186 deletions(-)
>
> [1]: https://lkml.org/lkml/2015/9/14/84
Oh, sorry I missed that. I review things that appear on linux-pci,
and several patches in this series weren't posted there, so I didn't
see them.
Bjorn
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
2015-10-06 17:47 ` Bjorn Helgaas
@ 2015-10-08 5:32 ` Jiang Liu
2015-10-08 13:20 ` Bjorn Helgaas
0 siblings, 1 reply; 11+ messages in thread
From: Jiang Liu @ 2015-10-08 5:32 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Rafael J. Wysocki,
Len Brown, linux-acpi, linux-kernel, x86, linux-pci
On 2015/10/7 1:47, Bjorn Helgaas wrote:
> Hi Jiang,
>
> Strictly speaking, this patch by itself doesn't actually "consolidate"
> anything because it only adds acpi_pci_root_create() (which isn't called by
> anything yet), but doesn't remove the original x86 copy.
>
<snit>
>> +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;
>> + ret = acpi_pci_probe_root_resources(info);
>> + if (ops->prepare_resources)
>> + ret = ops->prepare_resources(info, ret);
>> + if (ret < 0)
>> + goto out_release_info;
>> + else if (ret > 0)
>> + pci_acpi_root_add_resources(info);
>
> This is unnecessarily complicated: you set "ret", then overwrite it if
> ops->prepare_resources. By the time you test "ret", it's messy to
> figure out what it means.
>
> Both ops->prepare_resources() and pci_acpi_root_add_resources()
> should be able to deal with empty resource lists, so can you do the
> following instead?
>
> ret = acpi_pci_probe_root_resources(info);
> if (ret < 0)
> goto out_release_info;
Hi Bjorn,
Thanks for review:)
The original code is used to handle a special case for x86,
where acpi_pci_probe_root_resources() fails but ops->prepare_resources()
succeeds. For x86, PCI host bridge resources may probed by means
other than ACPI when pci_use_crs is true (AMD and Broadcom hostbridges).
So we can't return failure when acpi_pci_probe_root_resources() fails.
+ ret = acpi_pci_probe_root_resources(info);
+ if (ops->prepare_resources)
+ ret = ops->prepare_resources(info, ret);
+ if (ret < 0)
+ goto out_release_info;
> if (ops->prepare_resources) {
> ret = ops->prepare_resources(info, ret);
> if (ret < 0)
> goto out_release_info;
> }
> pci_acpi_root_add_resources(info);
I will remove the redundant check of (ret > 0) in:
+ else if (ret > 0)
+ pci_acpi_root_add_resources(info);
>
>> + pci_add_resource(&info->resources, &root->secondary);
>> +
>> + bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
>> + sysdata, &info->resources);
>> + if (bus) {
>
> if (!bus)
> goto out_release_info;
>
> Then it looks like the other error paths above, and you can un-indent
> the following code, which is the normal path:
Will do this.
Thanks!
Gerry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
2015-10-08 5:32 ` Jiang Liu
@ 2015-10-08 13:20 ` Bjorn Helgaas
2015-10-09 8:19 ` Jiang Liu
0 siblings, 1 reply; 11+ messages in thread
From: Bjorn Helgaas @ 2015-10-08 13:20 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Rafael J. Wysocki,
Len Brown, linux-acpi, linux-kernel, x86, linux-pci
On Thu, Oct 08, 2015 at 01:32:04PM +0800, Jiang Liu wrote:
> On 2015/10/7 1:47, Bjorn Helgaas wrote:
> >> +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;
> >> + ret = acpi_pci_probe_root_resources(info);
> >> + if (ops->prepare_resources)
> >> + ret = ops->prepare_resources(info, ret);
> >> + if (ret < 0)
> >> + goto out_release_info;
> >> + else if (ret > 0)
> >> + pci_acpi_root_add_resources(info);
> >
> > This is unnecessarily complicated: you set "ret", then overwrite it if
> > ops->prepare_resources. By the time you test "ret", it's messy to
> > figure out what it means.
> >
> > Both ops->prepare_resources() and pci_acpi_root_add_resources()
> > should be able to deal with empty resource lists, so can you do the
> > following instead?
> >
> > ret = acpi_pci_probe_root_resources(info);
> > if (ret < 0)
> > goto out_release_info;
>
> The original code is used to handle a special case for x86,
> where acpi_pci_probe_root_resources() fails but ops->prepare_resources()
> succeeds. For x86, PCI host bridge resources may probed by means
> other than ACPI when pci_use_crs is true (AMD and Broadcom hostbridges).
> So we can't return failure when acpi_pci_probe_root_resources() fails.
That's even worse than I thought. I take back my ack; I think this
really needs to be restructured so it does the right thing *and* reads
clearly. Having convoluted generic code to deal with an arch-specific
special case is a recipe for breakage in the future.
Maybe you can move the non-ACPI resource probing from
prepare_resources() into acpi_pci_probe_root_resources() (you could
rename it to something more generic if that helps).
> + ret = acpi_pci_probe_root_resources(info);
> + if (ops->prepare_resources)
> + ret = ops->prepare_resources(info, ret);
> + if (ret < 0)
> + goto out_release_info;
>
> > if (ops->prepare_resources) {
> > ret = ops->prepare_resources(info, ret);
> > if (ret < 0)
> > goto out_release_info;
> > }
> > pci_acpi_root_add_resources(info);
> I will remove the redundant check of (ret > 0) in:
> + else if (ret > 0)
> + pci_acpi_root_add_resources(info);
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core
2015-10-08 13:20 ` Bjorn Helgaas
@ 2015-10-09 8:19 ` Jiang Liu
0 siblings, 0 replies; 11+ messages in thread
From: Jiang Liu @ 2015-10-09 8:19 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, Rafael J . Wysocki, Lorenzo Pieralisi,
Marc Zyngier, Hanjun Guo, Liviu Dudau, Rafael J. Wysocki,
Len Brown, linux-acpi, linux-kernel, x86, linux-pci
On 2015/10/8 21:20, Bjorn Helgaas wrote:
> On Thu, Oct 08, 2015 at 01:32:04PM +0800, Jiang Liu wrote:
>> On 2015/10/7 1:47, Bjorn Helgaas wrote:
>>>> +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;
>>>> + ret = acpi_pci_probe_root_resources(info);
>>>> + if (ops->prepare_resources)
>>>> + ret = ops->prepare_resources(info, ret);
>>>> + if (ret < 0)
>>>> + goto out_release_info;
>>>> + else if (ret > 0)
>>>> + pci_acpi_root_add_resources(info);
>>>
>>> This is unnecessarily complicated: you set "ret", then overwrite it if
>>> ops->prepare_resources. By the time you test "ret", it's messy to
>>> figure out what it means.
>>>
>>> Both ops->prepare_resources() and pci_acpi_root_add_resources()
>>> should be able to deal with empty resource lists, so can you do the
>>> following instead?
>>>
>>> ret = acpi_pci_probe_root_resources(info);
>>> if (ret < 0)
>>> goto out_release_info;
>>
>> The original code is used to handle a special case for x86,
>> where acpi_pci_probe_root_resources() fails but ops->prepare_resources()
>> succeeds. For x86, PCI host bridge resources may probed by means
>> other than ACPI when pci_use_crs is true (AMD and Broadcom hostbridges).
>> So we can't return failure when acpi_pci_probe_root_resources() fails.
>
> That's even worse than I thought. I take back my ack; I think this
> really needs to be restructured so it does the right thing *and* reads
> clearly. Having convoluted generic code to deal with an arch-specific
> special case is a recipe for breakage in the future.
>
> Maybe you can move the non-ACPI resource probing from
> prepare_resources() into acpi_pci_probe_root_resources() (you could
> rename it to something more generic if that helps).
Hi Bjorn,
How about this solution?
1) export acpi_pci_probe_root_resources() as a helper to arch code
2) change ACPI core code as below
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;
By this way, if arch has special requirement, it could implement
prepare_resources callback and make use of
acpi_pci_probe_root_resources() if needed.
Thanks!
Gerry
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2015-10-09 8:19 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1442218057-4355-1-git-send-email-jiang.liu@linux.intel.com>
2015-09-14 8:07 ` [Patch v6 4/7] PCI/ACPI: Consolidate common PCI host bridge code into ACPI core Jiang Liu
2015-10-06 17:47 ` Bjorn Helgaas
2015-10-08 5:32 ` Jiang Liu
2015-10-08 13:20 ` Bjorn Helgaas
2015-10-09 8:19 ` Jiang Liu
2015-09-14 8:07 ` [Patch v6 5/7] ACPI, PCI: Reset acpi_root_dev->domain to 0 when pci_ignore_seg is set Jiang Liu
2015-10-06 17:54 ` Bjorn Helgaas
2015-09-14 8:07 ` [Patch v6 6/7] x86/PCI/ACPI: Use common interface to support PCI host bridge Jiang Liu
2015-10-06 18:01 ` Bjorn Helgaas
2015-10-07 8:52 ` Hanjun Guo
2015-10-07 12:45 ` Bjorn Helgaas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).