All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges
@ 2012-06-19 13:15 Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 01/12] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Jiang Liu
                   ` (11 more replies)
  0 siblings, 12 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci

This patchset enhance pci_root driver to update MMCFG information when
hot-plugging PCI root bridges. It applies to 
git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git pci/next-3.5

-v2: split into smaller patches and skip updating MMCFG information when
     MMCFG is disabled
-v3: add mmconf_added to simply free path, also make pci_mmconfig_insert()
     to process extra exist case --- By Yinghai
-v4: tune arch_acpi_pci_root_add() to handle a corner case raised by Kenji
-v5: address review comments from Bjorn and Taku, also better handle corner
     cases in arch_acpi_pci_root_add()
-v6: get rid of arch_acpi_pci_root_xxx() by using existing hooks
     add MCFG information for host bridges on demand
     more corner cases clear up
     correctly handle condition compilation
     fix section mismatch issues
     fix a issue reported by Taku about a BIOS bug
-v7: unify log messages
     remove redundant host bridge resource related log messages
     fix a issue reported by Taku which breaks pnp resource allocation
-v8: 1) add acpi_pci_cache_mcfg() in patch "provide MCFG address for PCI host
     bridges" for better readability and fix a condition compilation issue
     2) change patch "add MMCFG information on demand" to RFC and fix
     compilation issues reported by Fengguang
     3) Add new patch "refine __pci_mmcfg_init() for better code readability"
      and "mark acpi_sfi_table_parse() as __init", there should no
      functionality changes.

Jiang Liu (12):
  x86/PCI: split out pci_mmcfg_check_reserved() for code reuse
  x86/PCI: split out pci_mmconfig_alloc() for code reuse
  x86/PCI: use RCU list to protect mmconfig list
  x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
  x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge
    hotplug
  PCI/ACPI: provide MCFG address for PCI host bridges
  x86/PCI: update MMCFG information when hot-plugging PCI host bridges
  x86/PCI: simplify pci_mmcfg_late_insert_resources()
  x86/PCI: get rid of redundant log messages
  x86/PCI: refine __pci_mmcfg_init() for better code readability
  ACPI: mark acpi_sfi_table_parse() as __init
  x86/PCI: add MMCFG information on demand

 arch/x86/include/asm/pci_x86.h |   12 ++
 arch/x86/pci/acpi.c            |   76 +++++++-
 arch/x86/pci/legacy.c          |    1 +
 arch/x86/pci/mmconfig-shared.c |  429 +++++++++++++++++++++++++++++-----------
 arch/x86/pci/mmconfig_32.c     |   30 +++-
 arch/x86/pci/mmconfig_64.c     |   37 +++-
 drivers/acpi/pci_root.c        |   12 ++
 drivers/pci/pci-acpi.c         |   60 ++++++
 include/acpi/acnames.h         |    1 +
 include/acpi/acpi_bus.h        |    3 +
 include/linux/pci-acpi.h       |    5 +
 include/linux/sfi_acpi.h       |    4 +-
 12 files changed, 536 insertions(+), 134 deletions(-)



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

* [PATCH v8 01/12] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 02/12] x86/PCI: split out pci_mmconfig_alloc() " Jiang Liu
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Split out pci_mmcfg_check_reserved() for code reuse, which will be used
when supporting PCI host bridge hotplug.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/pci/mmconfig-shared.c |   51 +++++++++++++++++++--------------------
 1 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 301e325..f799949 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -474,39 +474,38 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
 	return valid;
 }
 
+static int __devinit pci_mmcfg_check_reserved(struct pci_mmcfg_region *cfg,
+					      int early)
+{
+	if (!early && !acpi_disabled) {
+		if (is_mmconf_reserved(is_acpi_reserved, cfg, 0))
+			return 1;
+		else
+			printk(KERN_ERR FW_BUG PREFIX
+			       "MMCONFIG at %pR not reserved in "
+			       "ACPI motherboard resources\n",
+			       &cfg->res);
+	}
+
+	/* Don't try to do this check unless configuration
+	   type 1 is available. how about type 2 ?*/
+	if (raw_pci_ops)
+		return is_mmconf_reserved(e820_all_mapped, cfg, 1);
+
+	return 0;
+}
+
 static void __init pci_mmcfg_reject_broken(int early)
 {
 	struct pci_mmcfg_region *cfg;
 
 	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
-		int valid = 0;
-
-		if (!early && !acpi_disabled) {
-			valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0);
-
-			if (valid)
-				continue;
-			else
-				printk(KERN_ERR FW_BUG PREFIX
-				       "MMCONFIG at %pR not reserved in "
-				       "ACPI motherboard resources\n",
-				       &cfg->res);
+		if (pci_mmcfg_check_reserved(cfg, early) == 0) {
+			printk(KERN_INFO PREFIX "not using MMCONFIG\n");
+			free_all_mmcfg();
+			return;
 		}
-
-		/* Don't try to do this check unless configuration
-		   type 1 is available. how about type 2 ?*/
-		if (raw_pci_ops)
-			valid = is_mmconf_reserved(e820_all_mapped, cfg, 1);
-
-		if (!valid)
-			goto reject;
 	}
-
-	return;
-
-reject:
-	printk(KERN_INFO PREFIX "not using MMCONFIG\n");
-	free_all_mmcfg();
 }
 
 static int __initdata known_bridge;
-- 
1.7.1



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

* [PATCH v8 02/12] x86/PCI: split out pci_mmconfig_alloc() for code reuse
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 01/12] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 03/12] x86/PCI: use RCU list to protect mmconfig list Jiang Liu
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Split out pci_mmconfig_alloc() for code reuse, which will be used
when supporting PCI root bridge hotplug.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/pci/mmconfig-shared.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index f799949..5e2cd2a 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -61,8 +61,9 @@ static __init void list_add_sorted(struct pci_mmcfg_region *new)
 	list_add_tail(&new->list, &pci_mmcfg_list);
 }
 
-static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
-							int end, u64 addr)
+static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment,
+							     int start,
+							     int end, u64 addr)
 {
 	struct pci_mmcfg_region *new;
 	struct resource *res;
@@ -79,8 +80,6 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
 	new->start_bus = start;
 	new->end_bus = end;
 
-	list_add_sorted(new);
-
 	res = &new->res;
 	res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
 	res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
@@ -96,6 +95,18 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
 	return new;
 }
 
+static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
+							int end, u64 addr)
+{
+	struct pci_mmcfg_region *new;
+
+	new = pci_mmconfig_alloc(segment, start, end, addr);
+	if (new)
+		list_add_sorted(new);
+
+	return new;
+}
+
 struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
 {
 	struct pci_mmcfg_region *cfg;
-- 
1.7.1



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

* [PATCH v8 03/12] x86/PCI: use RCU list to protect mmconfig list
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 01/12] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 02/12] x86/PCI: split out pci_mmconfig_alloc() " Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 04/12] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Jiang Liu
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Use RCU list to protect mmconfig list from dynamic change
when supporting PCI host bridge hotplug.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/pci/mmconfig-shared.c |   18 ++++++++++++------
 arch/x86/pci/mmconfig_32.c     |   13 +++++++++++--
 arch/x86/pci/mmconfig_64.c     |   13 +++++++++++--
 3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 5e2cd2a..0ac97d5 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -17,6 +17,8 @@
 #include <linux/bitmap.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/rculist.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
 #include <asm/acpi.h>
@@ -25,6 +27,7 @@
 
 /* Indicate if the mmcfg resources have been placed into the resource table. */
 static int __initdata pci_mmcfg_resources_inserted;
+static DEFINE_MUTEX(pci_mmcfg_lock);
 
 LIST_HEAD(pci_mmcfg_list);
 
@@ -45,20 +48,20 @@ static __init void free_all_mmcfg(void)
 		pci_mmconfig_remove(cfg);
 }
 
-static __init void list_add_sorted(struct pci_mmcfg_region *new)
+static __devinit void list_add_sorted(struct pci_mmcfg_region *new)
 {
 	struct pci_mmcfg_region *cfg;
 
 	/* keep list sorted by segment and starting bus number */
-	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
 		if (cfg->segment > new->segment ||
 		    (cfg->segment == new->segment &&
 		     cfg->start_bus >= new->start_bus)) {
-			list_add_tail(&new->list, &cfg->list);
+			list_add_tail_rcu(&new->list, &cfg->list);
 			return;
 		}
 	}
-	list_add_tail(&new->list, &pci_mmcfg_list);
+	list_add_tail_rcu(&new->list, &pci_mmcfg_list);
 }
 
 static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment,
@@ -101,8 +104,11 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
 	struct pci_mmcfg_region *new;
 
 	new = pci_mmconfig_alloc(segment, start, end, addr);
-	if (new)
+	if (new) {
+		mutex_lock(&pci_mmcfg_lock);
 		list_add_sorted(new);
+		mutex_unlock(&pci_mmcfg_lock);
+	}
 
 	return new;
 }
@@ -111,7 +117,7 @@ struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
 {
 	struct pci_mmcfg_region *cfg;
 
-	list_for_each_entry(cfg, &pci_mmcfg_list, list)
+	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
 		if (cfg->segment == segment &&
 		    cfg->start_bus <= bus && bus <= cfg->end_bus)
 			return cfg;
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index 5372e86..5dad04a 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -11,6 +11,7 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/rcupdate.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
 #include <acpi/acpi.h>
@@ -60,9 +61,12 @@ err:		*value = -1;
 		return -EINVAL;
 	}
 
+	rcu_read_lock();
 	base = get_base_addr(seg, bus, devfn);
-	if (!base)
+	if (!base) {
+		rcu_read_unlock();
 		goto err;
+	}
 
 	raw_spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -80,6 +84,7 @@ err:		*value = -1;
 		break;
 	}
 	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+	rcu_read_unlock();
 
 	return 0;
 }
@@ -93,9 +98,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 	if ((bus > 255) || (devfn > 255) || (reg > 4095))
 		return -EINVAL;
 
+	rcu_read_lock();
 	base = get_base_addr(seg, bus, devfn);
-	if (!base)
+	if (!base) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
 	raw_spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -113,6 +121,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 		break;
 	}
 	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+	rcu_read_unlock();
 
 	return 0;
 }
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index 915a493..acc48c5 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -9,6 +9,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
+#include <linux/rcupdate.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
 
@@ -34,9 +35,12 @@ err:		*value = -1;
 		return -EINVAL;
 	}
 
+	rcu_read_lock();
 	addr = pci_dev_base(seg, bus, devfn);
-	if (!addr)
+	if (!addr) {
+		rcu_read_unlock();
 		goto err;
+	}
 
 	switch (len) {
 	case 1:
@@ -49,6 +53,7 @@ err:		*value = -1;
 		*value = mmio_config_readl(addr + reg);
 		break;
 	}
+	rcu_read_unlock();
 
 	return 0;
 }
@@ -62,9 +67,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
 		return -EINVAL;
 
+	rcu_read_lock();
 	addr = pci_dev_base(seg, bus, devfn);
-	if (!addr)
+	if (!addr) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
 	switch (len) {
 	case 1:
@@ -77,6 +85,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 		mmio_config_writel(addr + reg, value);
 		break;
 	}
+	rcu_read_unlock();
 
 	return 0;
 }
-- 
1.7.1



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

* [PATCH v8 04/12] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (2 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 03/12] x86/PCI: use RCU list to protect mmconfig list Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 05/12] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Jiang Liu
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap(), which will be used
when supporting PCI root bridge hotplug.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/include/asm/pci_x86.h |    2 ++
 arch/x86/pci/mmconfig_32.c     |   15 +++++++++++++++
 arch/x86/pci/mmconfig_64.c     |   22 +++++++++++++++++++++-
 3 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index b3a5317..df898ce 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -135,6 +135,8 @@ struct pci_mmcfg_region {
 
 extern int __init pci_mmcfg_arch_init(void);
 extern void __init pci_mmcfg_arch_free(void);
+extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
+extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
 extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
 
 extern struct list_head pci_mmcfg_list;
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index 5dad04a..a22785d 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -141,3 +141,18 @@ int __init pci_mmcfg_arch_init(void)
 void __init pci_mmcfg_arch_free(void)
 {
 }
+
+int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
+{
+	return 0;
+}
+
+void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
+{
+	unsigned long flags;
+
+	/* Invalidate the cached mmcfg map entry. */
+	raw_spin_lock_irqsave(&pci_config_lock, flags);
+	mmcfg_last_accessed_device = 0;
+	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index acc48c5..4e05779 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -95,7 +95,7 @@ static const struct pci_raw_ops pci_mmcfg = {
 	.write =	pci_mmcfg_write,
 };
 
-static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg)
+static void __iomem * __devinit mcfg_ioremap(struct pci_mmcfg_region *cfg)
 {
 	void __iomem *addr;
 	u64 start, size;
@@ -138,3 +138,23 @@ void __init pci_mmcfg_arch_free(void)
 		}
 	}
 }
+
+int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
+{
+	cfg->virt = mcfg_ioremap(cfg);
+	if (!cfg->virt) {
+		printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
+		       &cfg->res);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
+{
+	if (cfg && cfg->virt) {
+		iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
+		cfg->virt = NULL;
+	}
+}
-- 
1.7.1



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

* [PATCH v8 05/12] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (3 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 04/12] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges Jiang Liu
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Introduce pci_mmconfig_insert()/pci_mmconfig_delete(), which will be used
to update MMCFG information when supporting PCI root bridge hotplug.

[bhelgaas: KERN_INFO, not KERN_ERR, for missing ACPI PNP0C01/02 reservation]
Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---

v8: add (cfg->address != addr) in function pci_mmconfig_insert()

---
 arch/x86/include/asm/pci_x86.h |    4 +
 arch/x86/pci/mmconfig-shared.c |  223 ++++++++++++++++++++++++++++++++-------
 2 files changed, 187 insertions(+), 40 deletions(-)

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index df898ce..af5018f 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -137,6 +137,10 @@ extern int __init pci_mmcfg_arch_init(void);
 extern void __init pci_mmcfg_arch_free(void);
 extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
 extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
+extern int __devinit pci_mmconfig_insert(struct device *dev,
+					 u16 seg, u8 start,
+					 u8 end, phys_addr_t addr);
+extern int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
 extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
 
 extern struct list_head pci_mmcfg_list;
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 0ac97d5..7d1c6bc 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -27,6 +27,8 @@
 
 /* Indicate if the mmcfg resources have been placed into the resource table. */
 static int __initdata pci_mmcfg_resources_inserted;
+static bool pci_mmcfg_running_state;
+static bool pci_mmcfg_arch_init_failed;
 static DEFINE_MUTEX(pci_mmcfg_lock);
 
 LIST_HEAD(pci_mmcfg_list);
@@ -91,10 +93,6 @@ static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment,
 		 "PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
 	res->name = new->name;
 
-	printk(KERN_INFO PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at "
-	       "%pR (base %#lx)\n", segment, start, end, &new->res,
-	       (unsigned long) addr);
-
 	return new;
 }
 
@@ -108,6 +106,11 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
 		mutex_lock(&pci_mmcfg_lock);
 		list_add_sorted(new);
 		mutex_unlock(&pci_mmcfg_lock);
+
+		printk(KERN_INFO PREFIX
+		       "MMCONFIG for domain %04x [bus %02x-%02x] at %pR "
+		       "(base %#lx)\n",
+		       segment, start, end, &new->res, (unsigned long)addr);
 	}
 
 	return new;
@@ -375,14 +378,15 @@ static void __init pci_mmcfg_insert_resources(void)
 	struct pci_mmcfg_region *cfg;
 
 	list_for_each_entry(cfg, &pci_mmcfg_list, list)
-		insert_resource(&iomem_resource, &cfg->res);
+		if (!cfg->res.parent)
+			insert_resource(&iomem_resource, &cfg->res);
 
 	/* Mark that the resources have been inserted. */
 	pci_mmcfg_resources_inserted = 1;
 }
 
-static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
-					      void *data)
+static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
+						 void *data)
 {
 	struct resource *mcfg_res = data;
 	struct acpi_resource_address64 address;
@@ -418,8 +422,8 @@ static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
 	return AE_OK;
 }
 
-static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
-		void *context, void **rv)
+static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl,
+						  void *context, void **rv)
 {
 	struct resource *mcfg_res = context;
 
@@ -432,7 +436,7 @@ static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
 	return AE_OK;
 }
 
-static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
+static int __devinit is_acpi_reserved(u64 start, u64 end, unsigned not_used)
 {
 	struct resource mcfg_res;
 
@@ -451,13 +455,15 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
 
 typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
 
-static int __init is_mmconf_reserved(check_reserved_t is_reserved,
-				    struct pci_mmcfg_region *cfg, int with_e820)
+static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
+				    struct pci_mmcfg_region *cfg,
+				    struct device *dev, int with_e820)
 {
 	u64 addr = cfg->res.start;
 	u64 size = resource_size(&cfg->res);
 	u64 old_size = size;
-	int valid = 0, num_buses;
+	int num_buses;
+	char *method = with_e820 ? "E820" : "ACPI motherboard resources";
 
 	while (!is_reserved(addr, addr + size, E820_RESERVED)) {
 		size >>= 1;
@@ -465,49 +471,75 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
 			break;
 	}
 
-	if (size >= (16UL<<20) || size == old_size) {
-		printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n",
-		       &cfg->res,
-		       with_e820 ? "E820" : "ACPI motherboard resources");
-		valid = 1;
-
-		if (old_size != size) {
-			/* update end_bus */
-			cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
-			num_buses = cfg->end_bus - cfg->start_bus + 1;
-			cfg->res.end = cfg->res.start +
-			    PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
-			snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
-				 "PCI MMCONFIG %04x [bus %02x-%02x]",
-				 cfg->segment, cfg->start_bus, cfg->end_bus);
+	if (size < (16UL<<20) && size != old_size)
+		return 0;
+
+	if (dev)
+		dev_info(dev, "MMCONFIG at %pR reserved in %s\n",
+			 &cfg->res, method);
+	else
+		printk(KERN_INFO PREFIX
+		       "MMCONFIG at %pR reserved in %s\n",
+		       &cfg->res, method);
+
+	if (old_size != size) {
+		/* update end_bus */
+		cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
+		num_buses = cfg->end_bus - cfg->start_bus + 1;
+		cfg->res.end = cfg->res.start +
+		    PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
+		snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
+			 "PCI MMCONFIG %04x [bus %02x-%02x]",
+			 cfg->segment, cfg->start_bus, cfg->end_bus);
+
+		if (dev)
+			dev_info(dev,
+				"MMCONFIG "
+				"at %pR (base %#lx) (size reduced!)\n",
+				&cfg->res, (unsigned long) cfg->address);
+		else
 			printk(KERN_INFO PREFIX
-			       "MMCONFIG for %04x [bus%02x-%02x] "
-			       "at %pR (base %#lx) (size reduced!)\n",
-			       cfg->segment, cfg->start_bus, cfg->end_bus,
-			       &cfg->res, (unsigned long) cfg->address);
-		}
+				"MMCONFIG for %04x [bus%02x-%02x] "
+				"at %pR (base %#lx) (size reduced!)\n",
+				cfg->segment, cfg->start_bus, cfg->end_bus,
+				&cfg->res, (unsigned long) cfg->address);
 	}
 
-	return valid;
+	return 1;
 }
 
-static int __devinit pci_mmcfg_check_reserved(struct pci_mmcfg_region *cfg,
-					      int early)
+static int __ref pci_mmcfg_check_reserved(struct device *dev,
+		  struct pci_mmcfg_region *cfg, int early)
 {
 	if (!early && !acpi_disabled) {
-		if (is_mmconf_reserved(is_acpi_reserved, cfg, 0))
+		if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0))
 			return 1;
+
+		if (dev)
+			dev_info(dev, FW_INFO
+				 "MMCONFIG at %pR not reserved in "
+				 "ACPI motherboard resources\n",
+				 &cfg->res);
 		else
-			printk(KERN_ERR FW_BUG PREFIX
+			printk(KERN_INFO FW_INFO PREFIX
 			       "MMCONFIG at %pR not reserved in "
 			       "ACPI motherboard resources\n",
 			       &cfg->res);
 	}
 
+	/*
+	 * e820_all_mapped() is marked as __init.
+	 * All entries from ACPI MCFG table have been checked at boot time.
+	 * For MCFG information constructed from hotpluggable host bridge's
+	 * _CBA method, just assume it's reserved.
+	 */
+	if (pci_mmcfg_running_state)
+		return 1;
+
 	/* Don't try to do this check unless configuration
 	   type 1 is available. how about type 2 ?*/
 	if (raw_pci_ops)
-		return is_mmconf_reserved(e820_all_mapped, cfg, 1);
+		return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1);
 
 	return 0;
 }
@@ -517,7 +549,7 @@ static void __init pci_mmcfg_reject_broken(int early)
 	struct pci_mmcfg_region *cfg;
 
 	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
-		if (pci_mmcfg_check_reserved(cfg, early) == 0) {
+		if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) {
 			printk(KERN_INFO PREFIX "not using MMCONFIG\n");
 			free_all_mmcfg();
 			return;
@@ -641,6 +673,7 @@ static void __init __pci_mmcfg_init(int early)
 		 * the architecture mmcfg setup could not initialize.
 		 */
 		pci_mmcfg_resources_inserted = 1;
+		pci_mmcfg_arch_init_failed = true;
 	}
 }
 
@@ -656,6 +689,8 @@ void __init pci_mmcfg_late_init(void)
 
 static int __init pci_mmcfg_late_insert_resources(void)
 {
+	pci_mmcfg_running_state = true;
+
 	/*
 	 * If resources are already inserted or we are not using MMCONFIG,
 	 * don't insert the resources.
@@ -681,3 +716,111 @@ static int __init pci_mmcfg_late_insert_resources(void)
  * with other system resources.
  */
 late_initcall(pci_mmcfg_late_insert_resources);
+
+/* Add MMCFG information for host bridges */
+int __devinit pci_mmconfig_insert(struct device *dev,
+				  u16 seg, u8 start, u8 end,
+				  phys_addr_t addr)
+{
+	int rc;
+	struct resource *tmp = NULL;
+	struct pci_mmcfg_region *cfg;
+
+	if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
+		return -ENODEV;
+
+	if (start > end)
+		return -EINVAL;
+
+	mutex_lock(&pci_mmcfg_lock);
+	cfg = pci_mmconfig_lookup(seg, start);
+	if (cfg) {
+		rc = -EEXIST;
+		if (cfg->address != addr) {
+			dev_err(dev, FW_BUG
+				 "detected address conflict when adding "
+				 "MMCONFIG for domain %04x [bus %02x-%02x],"
+				 " old addr [%#lx], new addr [%#lx].\n",
+				  cfg->segment, cfg->start_bus, cfg->end_bus,
+				  (unsigned long)cfg->address,
+				  (unsigned long)addr);
+			rc = -EINVAL;
+		} else if (cfg->end_bus < end)
+			dev_info(dev, FW_INFO
+				 "MMCONFIG for "
+				 "domain %04x [bus %02x-%02x] "
+				 "only partially covers this bridge\n",
+				  cfg->segment, cfg->start_bus, cfg->end_bus);
+		mutex_unlock(&pci_mmcfg_lock);
+		return rc;
+	}
+
+	if (!addr) {
+		mutex_unlock(&pci_mmcfg_lock);
+		return -EINVAL;
+	}
+
+	rc = -EBUSY;
+	cfg = pci_mmconfig_alloc(seg, start, end, addr);
+	if (cfg == NULL) {
+		dev_warn(dev, "fail to add MMCONFIG (out of memory)\n");
+		rc = -ENOMEM;
+	} else if (!pci_mmcfg_check_reserved(dev, cfg, 0)) {
+		dev_warn(dev, FW_BUG "MMCONFIG %pR isn't reserved\n",
+			 &cfg->res);
+	} else {
+		/* Insert resource if it's not in boot stage */
+		if (pci_mmcfg_running_state)
+			tmp = insert_resource_conflict(&iomem_resource,
+						       &cfg->res);
+
+		if (tmp) {
+			dev_warn(dev,
+				 "MMCONFIG %pR conflicts with "
+				 "%s %pR\n",
+				 &cfg->res, tmp->name, tmp);
+		} else if (pci_mmcfg_arch_map(cfg)) {
+			dev_warn(dev, "fail to map MMCONFIG %pR.\n",
+				 &cfg->res);
+		} else {
+			list_add_sorted(cfg);
+			dev_info(dev, "MMCONFIG at %pR (base %#lx)\n",
+				 &cfg->res, (unsigned long)addr);
+			cfg = NULL;
+			rc = 0;
+		}
+	}
+
+	if (cfg) {
+		if (cfg->res.parent)
+			release_resource(&cfg->res);
+		kfree(cfg);
+	}
+
+	mutex_unlock(&pci_mmcfg_lock);
+
+	return rc;
+}
+
+/* Delete MMCFG information for host bridges */
+int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
+{
+	struct pci_mmcfg_region *cfg;
+
+	mutex_lock(&pci_mmcfg_lock);
+	list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
+		if (cfg->segment == seg && cfg->start_bus == start &&
+		    cfg->end_bus == end) {
+			list_del_rcu(&cfg->list);
+			synchronize_rcu();
+			pci_mmcfg_arch_unmap(cfg);
+			if (cfg->res.parent)
+				release_resource(&cfg->res);
+			mutex_unlock(&pci_mmcfg_lock);
+			kfree(cfg);
+			return 0;
+		}
+	mutex_unlock(&pci_mmcfg_lock);
+
+	return -ENOENT;
+}
-- 
1.7.1



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

* [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (4 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 05/12] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 18:34   ` Yinghai Lu
  2012-06-19 13:15 ` [PATCH v8 07/12] x86/PCI: update MMCFG information when hot-plugging " Jiang Liu
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

This patch provide MCFG address for PCI host bridges, which will
be used to support host bridge hotplug.  It gets MCFG address
by evaluating _CBA method if available, or by scanning the ACPI
MCFG table.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---

v8: add acpi_pci_cache_mcfg() for better readable code and fix a condition
    compilation issue

---
 arch/x86/pci/mmconfig-shared.c |    4 ++
 drivers/acpi/pci_root.c        |   12 ++++++++
 drivers/pci/pci-acpi.c         |   60 ++++++++++++++++++++++++++++++++++++++++
 include/acpi/acnames.h         |    1 +
 include/acpi/acpi_bus.h        |    3 ++
 include/linux/pci-acpi.h       |    5 +++
 6 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 7d1c6bc..94ed360 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/rculist.h>
+#include <linux/pci-acpi.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
 #include <asm/acpi.h>
@@ -675,6 +676,9 @@ static void __init __pci_mmcfg_init(int early)
 		pci_mmcfg_resources_inserted = 1;
 		pci_mmcfg_arch_init_failed = true;
 	}
+
+	if (!early && !known_bridge)
+		acpi_pci_cache_mcfg();
 }
 
 void __init pci_mmcfg_early_init(void)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7aff631..3ce6a28 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -458,6 +458,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	acpi_handle handle;
 	struct acpi_device *child;
 	u32 flags, base_flags;
+	int end_bus = -1;
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
 	if (!root)
@@ -505,6 +506,17 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
 	device->driver_data = root;
 
+	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle,
+		root->segment, (u8) root->secondary.start, &end_bus);
+
+	/*
+	 * End bus number for MCFG may be less than root's subordinary
+	 * bus number with buggy BIOS implementation.
+	 */
+	if (end_bus < 0 || end_bus > root->secondary.end)
+		end_bus = root->secondary.end;
+	root->mcfg_end_bus = (u8) end_bus;
+
 	/*
 	 * All supported architectures that use ACPI have support for
 	 * PCI domains, so we indicate this in _OSC support capabilities.
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 61e2fef..0c6e0bb 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -162,6 +162,66 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
 	return remove_pm_notifier(dev, pci_acpi_wake_dev);
 }
 
+/* acpi_table_parse() is marked as __init, so cache MCFG info at boot time */
+static int pci_acpi_mcfg_entries;
+static struct acpi_mcfg_allocation *pci_acpi_mcfg_array;
+
+static int __init pci_cache_mcfg(struct acpi_table_header *header)
+{
+	u32 sz;
+	void *ptr;
+
+	if (!header || (header->length <= sizeof(struct acpi_table_mcfg)))
+		return -EINVAL;
+
+	sz = (header->length - sizeof(struct acpi_table_mcfg));
+	pci_acpi_mcfg_array = kmalloc(sz, GFP_KERNEL);
+	if (!pci_acpi_mcfg_array)
+		return -ENOMEM;
+
+	ptr = (void *)header + sizeof(struct acpi_table_mcfg);
+	memcpy(pci_acpi_mcfg_array, ptr, sz);
+	pci_acpi_mcfg_entries = sz / sizeof (struct acpi_mcfg_allocation);
+
+	return 0;
+}
+
+int __init acpi_pci_cache_mcfg(void)
+{
+	acpi_table_parse(ACPI_SIG_MCFG, pci_cache_mcfg);
+	return pci_acpi_mcfg_array ? 0 : -EINVAL;
+}
+
+phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle, u16 seg,
+					u8 start, int *endp)
+{
+	int i, end_bus = -1;
+	acpi_status status = AE_NOT_EXIST;
+	unsigned long long mcfg_addr = 0;
+	struct acpi_mcfg_allocation *cfg;
+
+	if (handle)
+		status = acpi_evaluate_integer(handle, METHOD_NAME__CBA,
+					       NULL, &mcfg_addr);
+	if (ACPI_FAILURE(status) && pci_acpi_mcfg_entries &&
+	    pci_acpi_mcfg_array) {
+		mcfg_addr = 0;
+		cfg = pci_acpi_mcfg_array;
+		for (i = 0; i < pci_acpi_mcfg_entries; i++, cfg++)
+			if (seg == cfg->pci_segment &&
+			    start >= cfg->start_bus_number &&
+			    start <= cfg->end_bus_number) {
+				end_bus = cfg->end_bus_number;
+				mcfg_addr = cfg->address;
+				break;
+			}
+	}
+	if (endp)
+		*endp = end_bus;
+
+	return (phys_addr_t)mcfg_addr;
+}
+
 /*
  * _SxD returns the D-state with the highest power
  * (lowest D-state number) supported in the S-state "x".
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index 38f5088..b177f97 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -62,6 +62,7 @@
 #define METHOD_NAME__AEI        "_AEI"
 #define METHOD_NAME__PRW        "_PRW"
 #define METHOD_NAME__SRS        "_SRS"
+#define METHOD_NAME__CBA        "_CBA"
 
 /* Method names - these methods must appear at the namespace root */
 
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 9e6e1c6..dc06515 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -401,6 +401,9 @@ struct acpi_pci_root {
 
 	u32 osc_support_set;	/* _OSC state of support bits */
 	u32 osc_control_set;	/* _OSC state of control bits */
+	u8 mcfg_end_bus;	/* End bus for MCFG may differ from
+				 * root's subordinate bus. */
+	phys_addr_t mcfg_addr;
 };
 
 /* helper */
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 4462350..e03207c 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -17,6 +17,9 @@ extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev);
 extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
 					     struct pci_dev *pci_dev);
 extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev);
+extern int acpi_pci_cache_mcfg(void);
+extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle,
+			u16 seg, u8 start, int *endp);
 
 static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
 {
@@ -35,6 +38,8 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 	return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus),
 					      pbus->number);
 }
+#else
+static inline int acpi_pci_cache_mcfg(void) { return -EINVAL; }
 #endif
 
 #ifdef CONFIG_ACPI_APEI
-- 
1.7.1



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

* [PATCH v8 07/12] x86/PCI: update MMCFG information when hot-plugging PCI host bridges
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (5 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 08/12] x86/PCI: simplify pci_mmcfg_late_insert_resources() Jiang Liu
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

This patch enhances x86 arch specific code to update MMCFG information
when PCI host bridge hotplug event happens.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/include/asm/pci_x86.h |    1 +
 arch/x86/pci/acpi.c            |   69 ++++++++++++++++++++++++++++++++++++++++
 arch/x86/pci/mmconfig-shared.c |    7 +---
 arch/x86/pci/mmconfig_32.c     |    2 +-
 arch/x86/pci/mmconfig_64.c     |    2 +-
 5 files changed, 73 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index af5018f..b2652e9 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -100,6 +100,7 @@ struct pci_raw_ops {
 extern const struct pci_raw_ops *raw_pci_ops;
 extern const struct pci_raw_ops *raw_pci_ext_ops;
 
+extern const struct pci_raw_ops pci_mmcfg;
 extern const struct pci_raw_ops pci_direct_conf1;
 extern bool port_cf9_safe;
 
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 2bb885a..4e0ed1e 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -4,6 +4,7 @@
 #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>
 
@@ -13,6 +14,12 @@ struct pci_root_info {
 	unsigned int res_num;
 	struct resource *res;
 	struct pci_sysdata sd;
+#ifdef	CONFIG_PCI_MMCONFIG
+	bool mcfg_added;
+	u16 segment;
+	u8 start_bus;
+	u8 end_bus;
+#endif
 };
 
 static bool pci_use_crs = true;
@@ -119,6 +126,61 @@ void __init pci_acpi_crs_quirks(void)
 	       pci_use_crs ? "nocrs" : "use_crs");
 }
 
+static int __devinit setup_mcfg_map(struct pci_root_info *info,
+				    u16 seg, u8 start, u8 end,
+				    phys_addr_t addr)
+{
+#ifdef	CONFIG_PCI_MMCONFIG
+	int result;
+	struct device *dev = &info->bridge->dev;
+
+	info->start_bus = start;
+	info->end_bus = end;
+	info->mcfg_added = false;
+
+	/* return success if MMCFG is not in use */
+	if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
+		return 0;
+
+	if (!(pci_probe & PCI_PROBE_MMCONF)) {
+		/* still could use raw_pci_ops for devices on segment 0 */
+		if (seg)
+			dev_warn(dev,
+				 "MMCONFIG is disabled, can't access extended "
+				 "configuration space under this bridge.\n");
+		return 0;
+	}
+
+	result = pci_mmconfig_insert(dev, seg, start, end, addr);
+	if (result == 0) {
+		/* enable MMCFG if it hasn't been enabled yet */
+		if (raw_pci_ext_ops == NULL)
+			raw_pci_ext_ops = &pci_mmcfg;
+		info->mcfg_added = true;
+	} else if (result != -EEXIST && addr) {
+		/*
+		 * Failure in adding MMCFG information is not fatal,
+		 * just can't access [extended] configuration space of
+		 * devices under this host bridge.
+		 */
+		dev_warn(dev, "fail to add MMCONFIG information.\n");
+	}
+#endif
+
+	return 0;
+}
+
+static void teardown_mcfg_map(struct pci_root_info *info)
+{
+#ifdef	CONFIG_PCI_MMCONFIG
+	if (info->mcfg_added) {
+		pci_mmconfig_delete(info->segment, info->start_bus,
+				    info->end_bus);
+		info->mcfg_added = false;
+	}
+#endif
+}
+
 static acpi_status
 resource_to_addr(struct acpi_resource *resource,
 			struct acpi_resource_address64 *addr)
@@ -331,6 +393,8 @@ static void __release_pci_root_info(struct pci_root_info *info)
 
 	free_pci_root_info_res(info);
 
+	teardown_mcfg_map(info);
+
 	kfree(info);
 }
 static void release_pci_root_info(struct pci_host_bridge *bridge)
@@ -438,6 +502,11 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
 			x86_pci_root_bus_resources(busnum, &resources);
 		}
 
+		if (root->mcfg_addr)
+			setup_mcfg_map(info, root->segment,
+				       (u8) root->secondary.start,
+				       root->mcfg_end_bus, root->mcfg_addr);
+
 		bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
 					  &resources);
 		if (bus) {
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 94ed360..48a9b8c 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -733,7 +733,7 @@ int __devinit pci_mmconfig_insert(struct device *dev,
 	if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
 		return -ENODEV;
 
-	if (start > end)
+	if (start > end || !addr)
 		return -EINVAL;
 
 	mutex_lock(&pci_mmcfg_lock);
@@ -759,11 +759,6 @@ int __devinit pci_mmconfig_insert(struct device *dev,
 		return rc;
 	}
 
-	if (!addr) {
-		mutex_unlock(&pci_mmcfg_lock);
-		return -EINVAL;
-	}
-
 	rc = -EBUSY;
 	cfg = pci_mmconfig_alloc(seg, start, end, addr);
 	if (cfg == NULL) {
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index a22785d..db63ac2 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -126,7 +126,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 	return 0;
 }
 
-static const struct pci_raw_ops pci_mmcfg = {
+const struct pci_raw_ops pci_mmcfg = {
 	.read =		pci_mmcfg_read,
 	.write =	pci_mmcfg_write,
 };
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index 4e05779..34c08dd 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -90,7 +90,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 	return 0;
 }
 
-static const struct pci_raw_ops pci_mmcfg = {
+const struct pci_raw_ops pci_mmcfg = {
 	.read =		pci_mmcfg_read,
 	.write =	pci_mmcfg_write,
 };
-- 
1.7.1



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

* [PATCH v8 08/12] x86/PCI: simplify pci_mmcfg_late_insert_resources()
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (6 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 07/12] x86/PCI: update MMCFG information when hot-plugging " Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 09/12] x86/PCI: get rid of redundant log messages Jiang Liu
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Reduce redundant code to simplify pci_mmcfg_late_insert_resources().

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/pci/mmconfig-shared.c |   34 ++++++++--------------------------
 1 files changed, 8 insertions(+), 26 deletions(-)

diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 48a9b8c..870ed3f 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -27,7 +27,6 @@
 #define PREFIX "PCI: "
 
 /* Indicate if the mmcfg resources have been placed into the resource table. */
-static int __initdata pci_mmcfg_resources_inserted;
 static bool pci_mmcfg_running_state;
 static bool pci_mmcfg_arch_init_failed;
 static DEFINE_MUTEX(pci_mmcfg_lock);
@@ -374,18 +373,6 @@ static int __init pci_mmcfg_check_hostbridge(void)
 	return !list_empty(&pci_mmcfg_list);
 }
 
-static void __init pci_mmcfg_insert_resources(void)
-{
-	struct pci_mmcfg_region *cfg;
-
-	list_for_each_entry(cfg, &pci_mmcfg_list, list)
-		if (!cfg->res.parent)
-			insert_resource(&iomem_resource, &cfg->res);
-
-	/* Mark that the resources have been inserted. */
-	pci_mmcfg_resources_inserted = 1;
-}
-
 static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
 						 void *data)
 {
@@ -669,11 +656,7 @@ static void __init __pci_mmcfg_init(int early)
 	if (pci_mmcfg_arch_init())
 		pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 	else {
-		/*
-		 * Signal not to attempt to insert mmcfg resources because
-		 * the architecture mmcfg setup could not initialize.
-		 */
-		pci_mmcfg_resources_inserted = 1;
+		free_all_mmcfg();
 		pci_mmcfg_arch_init_failed = true;
 	}
 
@@ -693,15 +676,12 @@ void __init pci_mmcfg_late_init(void)
 
 static int __init pci_mmcfg_late_insert_resources(void)
 {
+	struct pci_mmcfg_region *cfg;
+
 	pci_mmcfg_running_state = true;
 
-	/*
-	 * If resources are already inserted or we are not using MMCONFIG,
-	 * don't insert the resources.
-	 */
-	if ((pci_mmcfg_resources_inserted == 1) ||
-	    (pci_probe & PCI_PROBE_MMCONF) == 0 ||
-	    list_empty(&pci_mmcfg_list))
+	/* If we are not using MMCONFIG, don't insert the resources. */
+	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
 		return 1;
 
 	/*
@@ -709,7 +689,9 @@ static int __init pci_mmcfg_late_insert_resources(void)
 	 * marked so it won't cause request errors when __request_region is
 	 * called.
 	 */
-	pci_mmcfg_insert_resources();
+	list_for_each_entry(cfg, &pci_mmcfg_list, list)
+		if (!cfg->res.parent)
+			insert_resource(&iomem_resource, &cfg->res);
 
 	return 0;
 }
-- 
1.7.1



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

* [PATCH v8 09/12] x86/PCI: get rid of redundant log messages
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (7 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 08/12] x86/PCI: simplify pci_mmcfg_late_insert_resources() Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 10/12] x86/PCI: refine __pci_mmcfg_init() for better code readability Jiang Liu
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

For each resource of a PCI host bridge, the arch code and PCI
code log following messages:
"pci_root PNP0A08:00: host bridge window [io 0x0000-0x03af]",
"pci_bus 0000:00: root bus resource [io  0x0000-0x03af]"

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---
 arch/x86/pci/acpi.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 4e0ed1e..e72e412 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -295,13 +295,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	}
 
 	info->res_num++;
-	if (addr.translation_offset)
-		dev_info(&info->bridge->dev, "host bridge window %pR "
-			 "(PCI address [%#llx-%#llx])\n",
-			 res, res->start - addr.translation_offset,
-			 res->end - addr.translation_offset);
-	else
-		dev_info(&info->bridge->dev, "host bridge window %pR\n", res);
 
 	return AE_OK;
 }
-- 
1.7.1



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

* [PATCH v8 10/12] x86/PCI: refine __pci_mmcfg_init() for better code readability
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (8 preceding siblings ...)
  2012-06-19 13:15 ` [PATCH v8 09/12] x86/PCI: get rid of redundant log messages Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  2012-06-19 18:31   ` Yinghai Lu
  2012-06-19 13:15   ` Jiang Liu
  2012-06-19 13:15 ` [RFC PATCH v8 12/12] x86/PCI: add MMCFG information on demand Jiang Liu
  11 siblings, 1 reply; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Refine __pci_mmcfg_init() for better code readability.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
---
 arch/x86/pci/mmconfig-shared.c |   51 ++++++++++++++++++---------------------
 1 files changed, 24 insertions(+), 27 deletions(-)

diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 870ed3f..f8c967c 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -545,8 +545,6 @@ static void __init pci_mmcfg_reject_broken(int early)
 	}
 }
 
-static int __initdata known_bridge;
-
 static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
 					struct acpi_mcfg_allocation *cfg)
 {
@@ -618,28 +616,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
 
 static void __init __pci_mmcfg_init(int early)
 {
-	/* MMCONFIG disabled */
-	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-		return;
-
-	/* MMCONFIG already enabled */
-	if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
-		return;
-
-	/* for late to exit */
-	if (known_bridge)
-		return;
-
-	if (early) {
-		if (pci_mmcfg_check_hostbridge())
-			known_bridge = 1;
-	}
-
-	if (!known_bridge)
-		acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
-
 	pci_mmcfg_reject_broken(early);
-
 	if (list_empty(&pci_mmcfg_list))
 		return;
 
@@ -659,19 +636,39 @@ static void __init __pci_mmcfg_init(int early)
 		free_all_mmcfg();
 		pci_mmcfg_arch_init_failed = true;
 	}
-
-	if (!early && !known_bridge)
-		acpi_pci_cache_mcfg();
 }
 
+static int __initdata known_bridge;
+
 void __init pci_mmcfg_early_init(void)
 {
-	__pci_mmcfg_init(1);
+	if (pci_probe & PCI_PROBE_MMCONF) {
+		if (pci_mmcfg_check_hostbridge())
+			known_bridge = 1;
+		else
+			acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
+		__pci_mmcfg_init(1);
+	}
 }
 
 void __init pci_mmcfg_late_init(void)
 {
+	/* MMCONFIG disabled */
+	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+		return;
+
+	/* MMCONFIG already enabled */
+	if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
+		return;
+
+	if (known_bridge)
+		return;
+
+	acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
 	__pci_mmcfg_init(0);
+
+	if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
+		acpi_pci_cache_mcfg();
 }
 
 static int __init pci_mmcfg_late_insert_resources(void)
-- 
1.7.1



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

* [PATCH v8 11/12] ACPI: mark acpi_sfi_table_parse() as __init
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
@ 2012-06-19 13:15   ` Jiang Liu
  2012-06-19 13:15 ` [PATCH v8 02/12] x86/PCI: split out pci_mmconfig_alloc() " Jiang Liu
                     ` (10 subsequent siblings)
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige,
	Feng Tang, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-acpi, linux-pci, Jiang Liu

Mark function acpi_sfi_table_parse() as __init to avoid warning messages:
WARNING: vmlinux.o(.text+0x4cd2d2): Section mismatch in reference from the
function acpi_sfi_table_parse.clone.0() to the function
.init.text:pci_parse_mcfg()

Function acpi_sfi_table_parse() calls acpi_table_parse() and pci_parse_mcfg(),
which are both marked as __init. And currently acpi_sfi_table_parse() is used
by MMCONFIG to scan MCFG table at boot time only, so it's safe to mark
acpi_sfi_table_parse() as __init.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
---
 include/linux/sfi_acpi.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h
index c4a5a8c..631af63 100644
--- a/include/linux/sfi_acpi.h
+++ b/include/linux/sfi_acpi.h
@@ -66,7 +66,7 @@ extern int sfi_acpi_table_parse(char *signature, char *oem_id,
 				char *oem_table_id,
 				int (*handler)(struct acpi_table_header *));
 
-static inline int acpi_sfi_table_parse(char *signature,
+static inline int __init acpi_sfi_table_parse(char *signature,
 				int (*handler)(struct acpi_table_header *))
 {
 	if (!acpi_table_parse(signature, handler))
@@ -83,7 +83,7 @@ static inline int sfi_acpi_table_parse(char *signature, char *oem_id,
 	return -1;
 }
 
-static inline int acpi_sfi_table_parse(char *signature,
+static inline int __init acpi_sfi_table_parse(char *signature,
 				int (*handler)(struct acpi_table_header *))
 {
 	return acpi_table_parse(signature, handler);
-- 
1.7.1

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

* [PATCH v8 11/12] ACPI: mark acpi_sfi_table_parse() as __init
@ 2012-06-19 13:15   ` Jiang Liu
  0 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige,
	Feng Tang, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-acpi, linux-pci, Jiang Liu

Mark function acpi_sfi_table_parse() as __init to avoid warning messages:
WARNING: vmlinux.o(.text+0x4cd2d2): Section mismatch in reference from the
function acpi_sfi_table_parse.clone.0() to the function
.init.text:pci_parse_mcfg()

Function acpi_sfi_table_parse() calls acpi_table_parse() and pci_parse_mcfg(),
which are both marked as __init. And currently acpi_sfi_table_parse() is used
by MMCONFIG to scan MCFG table at boot time only, so it's safe to mark
acpi_sfi_table_parse() as __init.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
---
 include/linux/sfi_acpi.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h
index c4a5a8c..631af63 100644
--- a/include/linux/sfi_acpi.h
+++ b/include/linux/sfi_acpi.h
@@ -66,7 +66,7 @@ extern int sfi_acpi_table_parse(char *signature, char *oem_id,
 				char *oem_table_id,
 				int (*handler)(struct acpi_table_header *));
 
-static inline int acpi_sfi_table_parse(char *signature,
+static inline int __init acpi_sfi_table_parse(char *signature,
 				int (*handler)(struct acpi_table_header *))
 {
 	if (!acpi_table_parse(signature, handler))
@@ -83,7 +83,7 @@ static inline int sfi_acpi_table_parse(char *signature, char *oem_id,
 	return -1;
 }
 
-static inline int acpi_sfi_table_parse(char *signature,
+static inline int __init acpi_sfi_table_parse(char *signature,
 				int (*handler)(struct acpi_table_header *))
 {
 	return acpi_table_parse(signature, handler);
-- 
1.7.1



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

* [RFC PATCH v8 12/12] x86/PCI: add MMCFG information on demand
  2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
                   ` (10 preceding siblings ...)
  2012-06-19 13:15   ` Jiang Liu
@ 2012-06-19 13:15 ` Jiang Liu
  11 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-19 13:15 UTC (permalink / raw)
  To: Bjorn Helgaas, Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile
  Cc: Jiang Liu, Yijing Wang, Keping Chen, linux-pci, Jiang Liu

This patch changes mmconfig logic on x86 platforms to add MMCFG
information on demand instead of adding all MMCFG entries from
the ACPI MCFG table at boot time. So only MMCFG address ranges
used by active PCI host bridges will be actually mapped.

Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
---

v8: this patch is just for RFC now, there still ongoing discussion
    about creating MMCONFIG information on demand

---
 arch/x86/include/asm/pci_x86.h |    5 +++
 arch/x86/pci/legacy.c          |    1 +
 arch/x86/pci/mmconfig-shared.c |   76 ++++++++++++++++++++++++++++++++++-----
 3 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index b2652e9..0c0c1a7 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -142,6 +142,11 @@ extern int __devinit pci_mmconfig_insert(struct device *dev,
 					 u16 seg, u8 start,
 					 u8 end, phys_addr_t addr);
 extern int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
+#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_MMCONFIG)
+extern void pci_mmconfig_probe(u8 start);
+#else
+static inline void pci_mmconfig_probe(u8 start) { }
+#endif
 extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
 
 extern struct list_head pci_mmcfg_list;
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index a1df191..e9a2384 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -49,6 +49,7 @@ void __devinit pcibios_scan_specific_bus(int busn)
 		    l != 0x0000 && l != 0xffff) {
 			DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);
 			printk(KERN_INFO "PCI: Discovered peer bus %02x\n", busn);
+			pci_mmconfig_probe(busn);
 			pci_scan_bus_on_node(busn, &pci_root_ops, node);
 			return;
 		}
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index f8c967c..330831c 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -459,6 +459,14 @@ static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
 			break;
 	}
 
+	/*
+	 * For backward compatibility, we will adjust the MMCONFIG region
+	 * at boot time if it's only partially reserved by firmware.
+	 * For PCI host bridge hotplug at runtime, just reject it.
+	 */
+	if (pci_mmcfg_running_state && old_size != size)
+		return 0;
+
 	if (size < (16UL<<20) && size != old_size)
 		return 0;
 
@@ -602,6 +610,16 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
 			return -ENODEV;
 		}
 
+		/*
+		 * MMCFG information for host brideges will be added on demand
+		 * by pci_root driver if ACPI is enabled. But there are special
+		 * requirements for devices on segment 0, MMCFG information may
+		 * be needed for fixing hardware quirks and probing for hidden
+		 * buses.
+		 */
+		if (!acpi_disabled && cfg->pci_segment)
+			continue;
+
 		if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
 				   cfg->end_bus_number, cfg->address) == NULL) {
 			printk(KERN_WARNING PREFIX
@@ -614,7 +632,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
 	return 0;
 }
 
-static void __init __pci_mmcfg_init(int early)
+static void __init __pci_mmcfg_init(int early, bool create_on_demand)
 {
 	pci_mmcfg_reject_broken(early);
 	if (list_empty(&pci_mmcfg_list))
@@ -630,6 +648,13 @@ static void __init __pci_mmcfg_init(int early)
 		}
 	}
 
+	/*
+	 * Avoid redundant pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() calls
+	 * for each MMCONFIG entry if they will be created on demand.
+	 */
+	if (create_on_demand)
+		free_all_mmcfg();
+
 	if (pci_mmcfg_arch_init())
 		pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 	else {
@@ -647,28 +672,37 @@ void __init pci_mmcfg_early_init(void)
 			known_bridge = 1;
 		else
 			acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
-		__pci_mmcfg_init(1);
+		__pci_mmcfg_init(1, false);
 	}
 }
 
 void __init pci_mmcfg_late_init(void)
 {
+	bool create_on_demand;
+
 	/* MMCONFIG disabled */
 	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
 		return;
 
-	/* MMCONFIG already enabled */
-	if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
-		return;
-
 	if (known_bridge)
 		return;
 
-	acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
-	__pci_mmcfg_init(0);
+	/*
+	 * MMCONFIG information will be created on demand by pci_root driver
+	 * when binding to ACPI host bridge deivces.
+	 */
+	create_on_demand = (!acpi_disabled && !acpi_pci_cache_mcfg());
 
-	if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
-		acpi_pci_cache_mcfg();
+	/* pci_mmcfg_early_init() fails to setup MMCONFIG, try again. */
+	if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) {
+		acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
+		__pci_mmcfg_init(0, create_on_demand);
+	/*
+	 * Free MMCONFIG information created by pci_mmcfg_early_init()
+	 * if MMCONFIG information will be created on demand.
+	 */
+	} else if (create_on_demand)
+		free_all_mmcfg();
 }
 
 static int __init pci_mmcfg_late_insert_resources(void)
@@ -802,3 +836,25 @@ int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
 
 	return -ENOENT;
 }
+
+#ifdef	CONFIG_ACPI
+/* Probe MMCFG information for PCI bus blind probe */
+void __devinit pci_mmconfig_probe(u8 start)
+{
+	int end_bus, temp;
+	phys_addr_t addr;
+
+	if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
+		return;
+
+	addr = acpi_pci_root_get_mcfg_addr(NULL, 0, start, &end_bus);
+	if (addr && end_bus >= 0 && end_bus <= 255) {
+		for (temp = start + 1; temp <= end_bus; temp++)
+			if (pci_find_bus(0, temp))
+				break;
+
+		temp--;
+		pci_mmconfig_insert(NULL, 0, start, (u8) temp, addr);
+	}
+}
+#endif
-- 
1.7.1



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

* Re: [PATCH v8 10/12] x86/PCI: refine __pci_mmcfg_init() for better code readability
  2012-06-19 13:15 ` [PATCH v8 10/12] x86/PCI: refine __pci_mmcfg_init() for better code readability Jiang Liu
@ 2012-06-19 18:31   ` Yinghai Lu
  2012-06-20  8:50     ` Jiang Liu
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2012-06-19 18:31 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
	Yijing Wang, Keping Chen, linux-pci, Jiang Liu

On Tue, Jun 19, 2012 at 6:15 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> Refine __pci_mmcfg_init() for better code readability.
>
> Signed-off-by: Jiang Liu <liuj97@gmail.com>
> ---
>  arch/x86/pci/mmconfig-shared.c |   51 ++++++++++++++++++---------------------
>  1 files changed, 24 insertions(+), 27 deletions(-)
>
> diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
> index 870ed3f..f8c967c 100644
> --- a/arch/x86/pci/mmconfig-shared.c
> +++ b/arch/x86/pci/mmconfig-shared.c
> @@ -545,8 +545,6 @@ static void __init pci_mmcfg_reject_broken(int early)
>        }
>  }
>
> -static int __initdata known_bridge;
> -
>  static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
>                                        struct acpi_mcfg_allocation *cfg)
>  {
> @@ -618,28 +616,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
>
>  static void __init __pci_mmcfg_init(int early)
>  {
> -       /* MMCONFIG disabled */
> -       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
> -               return;
> -
> -       /* MMCONFIG already enabled */
> -       if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
> -               return;
> -
> -       /* for late to exit */
> -       if (known_bridge)
> -               return;
> -
> -       if (early) {
> -               if (pci_mmcfg_check_hostbridge())
> -                       known_bridge = 1;
> -       }
> -
> -       if (!known_bridge)
> -               acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
> -
>        pci_mmcfg_reject_broken(early);
> -
>        if (list_empty(&pci_mmcfg_list))
>                return;
>
> @@ -659,19 +636,39 @@ static void __init __pci_mmcfg_init(int early)
>                free_all_mmcfg();
>                pci_mmcfg_arch_init_failed = true;
>        }
> -
> -       if (!early && !known_bridge)
> -               acpi_pci_cache_mcfg();
>  }
>
> +static int __initdata known_bridge;
> +
>  void __init pci_mmcfg_early_init(void)
>  {
> -       __pci_mmcfg_init(1);
> +       if (pci_probe & PCI_PROBE_MMCONF) {
> +               if (pci_mmcfg_check_hostbridge())
> +                       known_bridge = 1;
> +               else
> +                       acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
> +               __pci_mmcfg_init(1);
> +       }
>  }
>
>  void __init pci_mmcfg_late_init(void)
>  {
> +       /* MMCONFIG disabled */
> +       if ((pci_probe & PCI_PROBE_MMCONF) == 0)
> +               return;
> +
> +       /* MMCONFIG already enabled */
> +       if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
> +               return;
> +
> +       if (known_bridge)
> +               return;
> +
> +       acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
>        __pci_mmcfg_init(0);
> +
> +       if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
> +               acpi_pci_cache_mcfg();
>  }
>
>  static int __init pci_mmcfg_late_insert_resources(void)

looks like MCFG is not cached when the entries is reserved through e820.
but it is cached when entries is reserved through ACPI ...

Please check if it is possible just not cache MCFG.

Thanks

Yinghai

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

* Re: [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges
  2012-06-19 13:15 ` [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges Jiang Liu
@ 2012-06-19 18:34   ` Yinghai Lu
  2012-06-20  8:32     ` Jiang Liu
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2012-06-19 18:34 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
	Yijing Wang, Keping Chen, linux-pci, Jiang Liu

On Tue, Jun 19, 2012 at 6:15 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> This patch provide MCFG address for PCI host bridges, which will
> be used to support host bridge hotplug.  It gets MCFG address
> by evaluating _CBA method if available, or by scanning the ACPI
> MCFG table.
>
> Signed-off-by: Jiang Liu <liuj97@gmail.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
>
> v8: add acpi_pci_cache_mcfg() for better readable code and fix a condition
>    compilation issue
>
> ---
>  arch/x86/pci/mmconfig-shared.c |    4 ++
>  drivers/acpi/pci_root.c        |   12 ++++++++
>  drivers/pci/pci-acpi.c         |   60 ++++++++++++++++++++++++++++++++++++++++
>  include/acpi/acnames.h         |    1 +
>  include/acpi/acpi_bus.h        |    3 ++
>  include/linux/pci-acpi.h       |    5 +++
>  6 files changed, 85 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
> index 7d1c6bc..94ed360 100644
> --- a/arch/x86/pci/mmconfig-shared.c
> +++ b/arch/x86/pci/mmconfig-shared.c
> @@ -19,6 +19,7 @@
>  #include <linux/slab.h>
>  #include <linux/mutex.h>
>  #include <linux/rculist.h>
> +#include <linux/pci-acpi.h>
>  #include <asm/e820.h>
>  #include <asm/pci_x86.h>
>  #include <asm/acpi.h>
> @@ -675,6 +676,9 @@ static void __init __pci_mmcfg_init(int early)
>                pci_mmcfg_resources_inserted = 1;
>                pci_mmcfg_arch_init_failed = true;
>        }
> +
> +       if (!early && !known_bridge)
> +               acpi_pci_cache_mcfg();
>  }
>
>  void __init pci_mmcfg_early_init(void)
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 7aff631..3ce6a28 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -458,6 +458,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
>        acpi_handle handle;
>        struct acpi_device *child;
>        u32 flags, base_flags;
> +       int end_bus = -1;
>
>        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
>        if (!root)
> @@ -505,6 +506,17 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
>        strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
>        device->driver_data = root;
>
> +       root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle,
> +               root->segment, (u8) root->secondary.start, &end_bus);
> +
> +       /*
> +        * End bus number for MCFG may be less than root's subordinary
> +        * bus number with buggy BIOS implementation.
> +        */
> +       if (end_bus < 0 || end_bus > root->secondary.end)
> +               end_bus = root->secondary.end;
> +       root->mcfg_end_bus = (u8) end_bus;
> +
>        /*
>         * All supported architectures that use ACPI have support for
>         * PCI domains, so we indicate this in _OSC support capabilities.
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 61e2fef..0c6e0bb 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -162,6 +162,66 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
>        return remove_pm_notifier(dev, pci_acpi_wake_dev);
>  }
>
> +/* acpi_table_parse() is marked as __init, so cache MCFG info at boot time */
> +static int pci_acpi_mcfg_entries;
> +static struct acpi_mcfg_allocation *pci_acpi_mcfg_array;
> +
> +static int __init pci_cache_mcfg(struct acpi_table_header *header)
> +{
> +       u32 sz;
> +       void *ptr;
> +
> +       if (!header || (header->length <= sizeof(struct acpi_table_mcfg)))
> +               return -EINVAL;
> +
> +       sz = (header->length - sizeof(struct acpi_table_mcfg));
> +       pci_acpi_mcfg_array = kmalloc(sz, GFP_KERNEL);
> +       if (!pci_acpi_mcfg_array)
> +               return -ENOMEM;
> +
> +       ptr = (void *)header + sizeof(struct acpi_table_mcfg);
> +       memcpy(pci_acpi_mcfg_array, ptr, sz);
> +       pci_acpi_mcfg_entries = sz / sizeof (struct acpi_mcfg_allocation);
> +
> +       return 0;
> +}

thought you were agreeing to go through choice 2 without caching MCFG anymore.

Can you just drop that caching MCFG and only handle _CBA here?

Thanks

Yinghai

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

* Re: [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges
  2012-06-19 18:34   ` Yinghai Lu
@ 2012-06-20  8:32     ` Jiang Liu
  2012-06-20 18:03       ` Yinghai Lu
  0 siblings, 1 reply; 20+ messages in thread
From: Jiang Liu @ 2012-06-20  8:32 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
	Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Hi Yinghai,
> thought you were agreeing to go through choice 2 without caching MCFG anymore.
> 
> Can you just drop that caching MCFG and only handle _CBA here?
> 
> Thanks
> 
> Yinghai

	Yes, I'm going to adopt solution two as you suggested. 
On the other hand, the MMCFG caching is kept due to following
considerations:
1) To emit a warning message if MMCFG entries in MCFG table only
partially covers buses under a PCI host bridge. Taku reported that
he has a system which exhibits such a behavior.
2) To cross-check that MMCFG addresses returned by MCFG table and 
_CBA method are consistent if both are available (though that 
violates the PCI FW/ACPI specifications).
3) In future, we may try to remove MMCFG entry constructed from
MCFG table when hot-removing a PCI host bridge. We have some systems
which assign a distinguish segment ID for each host bridge. In such
a case, it may be reasonable to remove the MMCFG entry when removing
a host bridge.
4) The MCFG cache should be small under normal cases.

	If you feel it's unnecessary to keep the cache, I will remove
it and send out a updated version soon.
	Thanks!
	Gerry


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

* Re: [PATCH v8 10/12] x86/PCI: refine __pci_mmcfg_init() for better code readability
  2012-06-19 18:31   ` Yinghai Lu
@ 2012-06-20  8:50     ` Jiang Liu
  0 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-20  8:50 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
	Yijing Wang, Keping Chen, linux-pci, Jiang Liu

On 2012-6-20 2:31, Yinghai Lu wrote:
> 
> looks like MCFG is not cached when the entries is reserved through e820.
> but it is cached when entries is reserved through ACPI ...
> 
> Please check if it is possible just not cache MCFG.
OOPS, my bad. The right logic should be
void __init pci_mmcfg_late_init(void)
{
        /* MMCONFIG disabled */
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
                return;

        if (known_bridge)
                return;

        /* MMCONFIG hasn't been enabled yet */
        if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) {
                acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
                __pci_mmcfg_init(0);
        }

        if (!(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
                acpi_pci_cache_mcfg();
}

Will send out a patch once we decide whether we should keep the MCFG cache.

Thanks!
Gerry


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

* Re: [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges
  2012-06-20  8:32     ` Jiang Liu
@ 2012-06-20 18:03       ` Yinghai Lu
  2012-06-21  1:36         ` Jiang Liu
  0 siblings, 1 reply; 20+ messages in thread
From: Yinghai Lu @ 2012-06-20 18:03 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
	Yijing Wang, Keping Chen, linux-pci, Jiang Liu

On Wed, Jun 20, 2012 at 1:32 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> Hi Yinghai,
>
>        Yes, I'm going to adopt solution two as you suggested.
> On the other hand, the MMCFG caching is kept due to following
> considerations:
> 1) To emit a warning message if MMCFG entries in MCFG table only
> partially covers buses under a PCI host bridge. Taku reported that
> he has a system which exhibits such a behavior.
Interesting.
that should have one overal checking after _CBA entry is added into
pci_mmcfg_list.
We limit root bus bus range after busn_alloc is there.
aka dump the bus range above mmcfg.
or user need to disable mmcfg.


> 2) To cross-check that MMCFG addresses returned by MCFG table and
> _CBA method are consistent if both are available (though that
> violates the PCI FW/ACPI specifications).

now we are adding support for pci hostbridge plug. so we should better to stick
with spec instead of trying to workaround possible FW problem.
Do spoil them too much.

my point is: MCFG is static. so the range from MCFG can not be changed after
they pass the sanity checking.
later if _CBA is trying come again with overlapping, just through that away.
then if _CBA is good, then just record the range, and later release the range
according the storage during hostbridge removal.

> 3) In future, we may try to remove MMCFG entry constructed from
> MCFG table when hot-removing a PCI host bridge. We have some systems
> which assign a distinguish segment ID for each host bridge. In such
> a case, it may be reasonable to remove the MMCFG entry when removing
> a host bridge.
No, MCFG is static one.

> 4) The MCFG cache should be small under normal cases.
>
>        If you feel it's unnecessary to keep the cache, I will remove
> it and send out a updated version soon.
for pci host bridge support, we would touch too much thing, I would
like to limit
first round change and keep it simple, and later could optimize it if possible.

Thanks

Yinghai

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

* Re: [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges
  2012-06-20 18:03       ` Yinghai Lu
@ 2012-06-21  1:36         ` Jiang Liu
  0 siblings, 0 replies; 20+ messages in thread
From: Jiang Liu @ 2012-06-21  1:36 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
	Yijing Wang, Keping Chen, linux-pci, Jiang Liu

Hi Yinghai,
	OK, I will send out v9 without the MCFG cache.
	Thanks!
	Gerry
On 2012-6-21 2:03, Yinghai Lu wrote:
> On Wed, Jun 20, 2012 at 1:32 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
>> Hi Yinghai,
>>
>>        Yes, I'm going to adopt solution two as you suggested.
>> On the other hand, the MMCFG caching is kept due to following
>> considerations:
>> 1) To emit a warning message if MMCFG entries in MCFG table only
>> partially covers buses under a PCI host bridge. Taku reported that
>> he has a system which exhibits such a behavior.
> Interesting.
> that should have one overal checking after _CBA entry is added into
> pci_mmcfg_list.
> We limit root bus bus range after busn_alloc is there.
> aka dump the bus range above mmcfg.
> or user need to disable mmcfg.
> 
> 
>> 2) To cross-check that MMCFG addresses returned by MCFG table and
>> _CBA method are consistent if both are available (though that
>> violates the PCI FW/ACPI specifications).
> 
> now we are adding support for pci hostbridge plug. so we should better to stick
> with spec instead of trying to workaround possible FW problem.
> Do spoil them too much.
> 
> my point is: MCFG is static. so the range from MCFG can not be changed after
> they pass the sanity checking.
> later if _CBA is trying come again with overlapping, just through that away.
> then if _CBA is good, then just record the range, and later release the range
> according the storage during hostbridge removal.
> 
>> 3) In future, we may try to remove MMCFG entry constructed from
>> MCFG table when hot-removing a PCI host bridge. We have some systems
>> which assign a distinguish segment ID for each host bridge. In such
>> a case, it may be reasonable to remove the MMCFG entry when removing
>> a host bridge.
> No, MCFG is static one.
> 
>> 4) The MCFG cache should be small under normal cases.
>>
>>        If you feel it's unnecessary to keep the cache, I will remove
>> it and send out a updated version soon.
> for pci host bridge support, we would touch too much thing, I would
> like to limit
> first round change and keep it simple, and later could optimize it if possible.
> 
> Thanks
> 
> Yinghai
> 
> .
> 



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

end of thread, other threads:[~2012-06-21  1:43 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-19 13:15 [PATCH v8 00/12] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
2012-06-19 13:15 ` [PATCH v8 01/12] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Jiang Liu
2012-06-19 13:15 ` [PATCH v8 02/12] x86/PCI: split out pci_mmconfig_alloc() " Jiang Liu
2012-06-19 13:15 ` [PATCH v8 03/12] x86/PCI: use RCU list to protect mmconfig list Jiang Liu
2012-06-19 13:15 ` [PATCH v8 04/12] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Jiang Liu
2012-06-19 13:15 ` [PATCH v8 05/12] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Jiang Liu
2012-06-19 13:15 ` [PATCH v8 06/12] PCI/ACPI: provide MCFG address for PCI host bridges Jiang Liu
2012-06-19 18:34   ` Yinghai Lu
2012-06-20  8:32     ` Jiang Liu
2012-06-20 18:03       ` Yinghai Lu
2012-06-21  1:36         ` Jiang Liu
2012-06-19 13:15 ` [PATCH v8 07/12] x86/PCI: update MMCFG information when hot-plugging " Jiang Liu
2012-06-19 13:15 ` [PATCH v8 08/12] x86/PCI: simplify pci_mmcfg_late_insert_resources() Jiang Liu
2012-06-19 13:15 ` [PATCH v8 09/12] x86/PCI: get rid of redundant log messages Jiang Liu
2012-06-19 13:15 ` [PATCH v8 10/12] x86/PCI: refine __pci_mmcfg_init() for better code readability Jiang Liu
2012-06-19 18:31   ` Yinghai Lu
2012-06-20  8:50     ` Jiang Liu
2012-06-19 13:15 ` [PATCH v8 11/12] ACPI: mark acpi_sfi_table_parse() as __init Jiang Liu
2012-06-19 13:15   ` Jiang Liu
2012-06-19 13:15 ` [RFC PATCH v8 12/12] x86/PCI: add MMCFG information on demand 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.