* [PATCH v9 01/11] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 9:36 ` [PATCH v9 02/11] x86/PCI: split out pci_mmconfig_alloc() " Jiang Liu
` (10 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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] 18+ messages in thread
* [PATCH v9 02/11] x86/PCI: split out pci_mmconfig_alloc() for code reuse
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
2012-06-21 9:36 ` [PATCH v9 01/11] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 9:36 ` [PATCH v9 03/11] x86/PCI: use RCU list to protect mmconfig list Jiang Liu
` (9 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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] 18+ messages in thread
* [PATCH v9 03/11] x86/PCI: use RCU list to protect mmconfig list
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
2012-06-21 9:36 ` [PATCH v9 01/11] x86/PCI: split out pci_mmcfg_check_reserved() for code reuse Jiang Liu
2012-06-21 9:36 ` [PATCH v9 02/11] x86/PCI: split out pci_mmconfig_alloc() " Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 9:36 ` [PATCH v9 04/11] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Jiang Liu
` (8 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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] 18+ messages in thread
* [PATCH v9 04/11] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (2 preceding siblings ...)
2012-06-21 9:36 ` [PATCH v9 03/11] x86/PCI: use RCU list to protect mmconfig list Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 21:25 ` Yinghai Lu
2012-06-21 9:36 ` [PATCH v9 05/11] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Jiang Liu
` (7 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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] 18+ messages in thread
* Re: [PATCH v9 04/11] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
2012-06-21 9:36 ` [PATCH v9 04/11] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Jiang Liu
@ 2012-06-21 21:25 ` Yinghai Lu
0 siblings, 0 replies; 18+ messages in thread
From: Yinghai Lu @ 2012-06-21 21:25 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
Yijing Wang, Keping Chen, linux-pci, Jiang Liu
On Thu, Jun 21, 2012 at 2:36 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> 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;
> + }
> +}
Can you merge pci_mmcfg_arch_map/unmap with pci_mmcfg_arch_init/free?
at least init/free could call map/unmap.
Thanks
Yinghai
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v9 05/11] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (3 preceding siblings ...)
2012-06-21 9:36 ` [PATCH v9 04/11] x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap() Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 21:44 ` Yinghai Lu
2012-06-21 9:36 ` [PATCH v9 06/11] PCI/ACPI: provide MCFG address for PCI host bridges Jiang Liu
` (6 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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>
---
arch/x86/include/asm/pci_x86.h | 4 +
arch/x86/pci/mmconfig-shared.c | 213 ++++++++++++++++++++++++++++++++--------
2 files changed, 177 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..19fc42b 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,101 @@ 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) {
+ 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 -EEXIST;
+ }
+
+ 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] 18+ messages in thread
* Re: [PATCH v9 05/11] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug
2012-06-21 9:36 ` [PATCH v9 05/11] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Jiang Liu
@ 2012-06-21 21:44 ` Yinghai Lu
0 siblings, 0 replies; 18+ messages in thread
From: Yinghai Lu @ 2012-06-21 21:44 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
Yijing Wang, Keping Chen, linux-pci, Jiang Liu
On Thu, Jun 21, 2012 at 2:36 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> 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>
> ---
> arch/x86/include/asm/pci_x86.h | 4 +
> arch/x86/pci/mmconfig-shared.c | 213 ++++++++++++++++++++++++++++++++--------
> 2 files changed, 177 insertions(+), 40 deletions(-)
this one is way to big, you may chop it to two or three.
>
> 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..19fc42b 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,101 @@ 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) {
> + 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 -EEXIST;
> + }
> +
> + 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
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v9 06/11] PCI/ACPI: provide MCFG address for PCI host bridges
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (4 preceding siblings ...)
2012-06-21 9:36 ` [PATCH v9 05/11] x86/PCI: add pci_mmconfig_insert()/delete() for PCI root bridge hotplug Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 9:36 ` [PATCH v9 07/11] x86/PCI: update MMCFG information when hot-plugging " Jiang Liu
` (5 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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>
---
drivers/acpi/pci_root.c | 2 ++
drivers/pci/pci-acpi.c | 14 ++++++++++++++
include/acpi/acnames.h | 1 +
include/acpi/acpi_bus.h | 1 +
include/linux/pci-acpi.h | 1 +
5 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7aff631..ec54014 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -505,6 +505,8 @@ 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);
+
/*
* 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..87f4c50 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -162,6 +162,20 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
return remove_pm_notifier(dev, pci_acpi_wake_dev);
}
+phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
+{
+ acpi_status status = AE_NOT_EXIST;
+ unsigned long long mcfg_addr;
+
+ if (handle)
+ status = acpi_evaluate_integer(handle, METHOD_NAME__CBA,
+ NULL, &mcfg_addr);
+ if (ACPI_FAILURE(status))
+ return 0;
+
+ 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..4579740 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -401,6 +401,7 @@ struct acpi_pci_root {
u32 osc_support_set; /* _OSC state of support bits */
u32 osc_control_set; /* _OSC state of control bits */
+ phys_addr_t mcfg_addr;
};
/* helper */
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 4462350..248fba2 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -17,6 +17,7 @@ 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 phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
{
--
1.7.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v9 07/11] x86/PCI: update MMCFG information when hot-plugging PCI host bridges
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (5 preceding siblings ...)
2012-06-21 9:36 ` [PATCH v9 06/11] PCI/ACPI: provide MCFG address for PCI host bridges Jiang Liu
@ 2012-06-21 9:36 ` Jiang Liu
2012-06-21 22:11 ` Yinghai Lu
2012-06-21 9:37 ` [PATCH v9 08/11] x86/PCI: simplify pci_mmcfg_late_insert_resources() Jiang Liu
` (4 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:36 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 | 71 ++++++++++++++++++++++++++++++++++++++++
arch/x86/pci/mmconfig_32.c | 2 +-
arch/x86/pci/mmconfig_64.c | 2 +-
4 files changed, 74 insertions(+), 2 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..f701179 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,8 +393,11 @@ 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)
{
struct pci_root_info *info = bridge->release_data;
@@ -438,6 +503,12 @@ 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,
+ (u8) root->secondary.end,
+ root->mcfg_addr);
+
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus) {
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] 18+ messages in thread
* Re: [PATCH v9 07/11] x86/PCI: update MMCFG information when hot-plugging PCI host bridges
2012-06-21 9:36 ` [PATCH v9 07/11] x86/PCI: update MMCFG information when hot-plugging " Jiang Liu
@ 2012-06-21 22:11 ` Yinghai Lu
0 siblings, 0 replies; 18+ messages in thread
From: Yinghai Lu @ 2012-06-21 22:11 UTC (permalink / raw)
To: Jiang Liu
Cc: Bjorn Helgaas, Taku Izumi, Kenji Kaneshige, Don Dutile,
Yijing Wang, Keping Chen, linux-pci, Jiang Liu
On Thu, Jun 21, 2012 at 2:36 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> 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 | 71 ++++++++++++++++++++++++++++++++++++++++
> arch/x86/pci/mmconfig_32.c | 2 +-
> arch/x86/pci/mmconfig_64.c | 2 +-
> 4 files changed, 74 insertions(+), 2 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..f701179 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;
> + }
that mean, user disable mmconf checking.
if it is with pci segment other than 0, that bridge can not be used
without MMCFG.
so should be:
> + if (seg)
> + return -EXXX;
> + 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");
need to check if seg is other 0.
> + }
> +#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,8 +393,11 @@ 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)
> {
> struct pci_root_info *info = bridge->release_data;
> @@ -438,6 +503,12 @@ 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,
> + (u8) root->secondary.end,
> + root->mcfg_addr);
> +
should check setup_mcfg_map return there. should skip the host bridge
if can not add MCFG for non 0 pci segment.
> bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
> &resources);
> if (bus) {
> 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
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v9 08/11] x86/PCI: simplify pci_mmcfg_late_insert_resources()
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (6 preceding siblings ...)
2012-06-21 9:36 ` [PATCH v9 07/11] x86/PCI: update MMCFG information when hot-plugging " Jiang Liu
@ 2012-06-21 9:37 ` Jiang Liu
2012-06-21 9:37 ` [PATCH v9 09/11] x86/PCI: get rid of redundant log messages Jiang Liu
` (3 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:37 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 19fc42b..332fabd 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -26,7 +26,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);
@@ -373,18 +372,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)
{
@@ -668,11 +655,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;
}
}
@@ -689,15 +672,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;
/*
@@ -705,7 +685,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] 18+ messages in thread
* [PATCH v9 09/11] x86/PCI: get rid of redundant log messages
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (7 preceding siblings ...)
2012-06-21 9:37 ` [PATCH v9 08/11] x86/PCI: simplify pci_mmcfg_late_insert_resources() Jiang Liu
@ 2012-06-21 9:37 ` Jiang Liu
2012-06-21 9:37 ` [PATCH v9 10/11] x86, PCI: refine __pci_mmcfg_init() for better code readability Jiang Liu
` (2 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:37 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 f701179..5f778ae 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] 18+ messages in thread
* [PATCH v9 10/11] x86, PCI: refine __pci_mmcfg_init() for better code readability
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (8 preceding siblings ...)
2012-06-21 9:37 ` [PATCH v9 09/11] x86/PCI: get rid of redundant log messages Jiang Liu
@ 2012-06-21 9:37 ` Jiang Liu
2012-06-21 9:37 ` [PATCH v9 11/11] ACPI: mark acpi_sfi_table_parse() as __init Jiang Liu
2012-06-21 20:06 ` [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Bjorn Helgaas
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:37 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 | 46 ++++++++++++++++++---------------------
1 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 332fabd..ffe72b9 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -544,8 +544,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)
{
@@ -617,28 +615,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;
@@ -660,14 +637,33 @@ static void __init __pci_mmcfg_init(int early)
}
}
+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)
{
- __pci_mmcfg_init(0);
+ /* MMCONFIG disabled */
+ if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ return;
+
+ if (known_bridge)
+ return;
+
+ /* MMCONFIG hasn't been enabled yet, 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);
+ }
}
static int __init pci_mmcfg_late_insert_resources(void)
--
1.7.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v9 11/11] ACPI: mark acpi_sfi_table_parse() as __init
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (9 preceding siblings ...)
2012-06-21 9:37 ` [PATCH v9 10/11] x86, PCI: refine __pci_mmcfg_init() for better code readability Jiang Liu
@ 2012-06-21 9:37 ` Jiang Liu
2012-06-21 20:06 ` [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Bjorn Helgaas
11 siblings, 0 replies; 18+ messages in thread
From: Jiang Liu @ 2012-06-21 9:37 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
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
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.
.init.text:pci_parse_mcfg()
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] 18+ messages in thread
* Re: [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges
2012-06-21 9:36 [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Jiang Liu
` (10 preceding siblings ...)
2012-06-21 9:37 ` [PATCH v9 11/11] ACPI: mark acpi_sfi_table_parse() as __init Jiang Liu
@ 2012-06-21 20:06 ` Bjorn Helgaas
2012-06-21 21:20 ` Yinghai Lu
2012-06-21 22:22 ` Yinghai Lu
11 siblings, 2 replies; 18+ messages in thread
From: Bjorn Helgaas @ 2012-06-21 20:06 UTC (permalink / raw)
To: Jiang Liu
Cc: Yinghai Lu, Taku Izumi, Kenji Kaneshige, Don Dutile, Yijing Wang,
Keping Chen, linux-pci
On Thu, Jun 21, 2012 at 3:36 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
> 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
Yinghai, I'm hoping you will review these. I'd like to get them into
-next soon and you're the main person paying attention to them :) If
you can't, let me know and I'll give it a go myself.
Bjorn
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges
2012-06-21 20:06 ` [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Bjorn Helgaas
@ 2012-06-21 21:20 ` Yinghai Lu
2012-06-21 22:22 ` Yinghai Lu
1 sibling, 0 replies; 18+ messages in thread
From: Yinghai Lu @ 2012-06-21 21:20 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Jiang Liu, Taku Izumi, Kenji Kaneshige, Don Dutile, Yijing Wang,
Keping Chen, linux-pci
On Thu, Jun 21, 2012 at 1:06 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Thu, Jun 21, 2012 at 3:36 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
>> 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
>
> Yinghai, I'm hoping you will review these. I'd like to get them into
> -next soon and you're the main person paying attention to them :) If
> you can't, let me know and I'll give it a go myself.
ok, I will check them today.
Yinghai
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges
2012-06-21 20:06 ` [PATCH v9 00/11] PCI, x86: update MMCFG information when hot-plugging PCI host bridges Bjorn Helgaas
2012-06-21 21:20 ` Yinghai Lu
@ 2012-06-21 22:22 ` Yinghai Lu
1 sibling, 0 replies; 18+ messages in thread
From: Yinghai Lu @ 2012-06-21 22:22 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Jiang Liu, Taku Izumi, Kenji Kaneshige, Don Dutile, Yijing Wang,
Keping Chen, linux-pci
On Thu, Jun 21, 2012 at 1:06 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Thu, Jun 21, 2012 at 3:36 AM, Jiang Liu <jiang.liu@huawei.com> wrote:
>> 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
>
> Yinghai, I'm hoping you will review these. I'd like to get them into
> -next soon and you're the main person paying attention to them :) If
> you can't, let me know and I'll give it a go myself.
Hi, Bjorn,
Only
[PATCH v9 07/11] x86/PCI: update MMCFG information when hot-plugging
PCI host bridges
still have problem with non-0 segment handling on failing path.
So assume us time tonight, and china time friday daytime, Jiang could fix it.
otherwise I will fix it tomorrow morning, then you could merge tomorrow noon.
Thanks
Yinghai
^ permalink raw reply [flat|nested] 18+ messages in thread