x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
authorJiang Liu <jiang.liu@huawei.com>
Fri, 22 Jun 2012 06:55:13 +0000 (14:55 +0800)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 22 Jun 2012 21:16:31 +0000 (15:16 -0600)
Introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap(), which will be used
when supporting PCI root bridge hotplug.

Reviewed-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <liuj97@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
arch/x86/include/asm/pci_x86.h
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c

index b3a5317..df898ce 100644 (file)
@@ -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;
index 5dad04a..a22785d 100644 (file)
@@ -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);
+}
index acc48c5..ebefea5 100644 (file)
@@ -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;
@@ -114,16 +114,14 @@ int __init pci_mmcfg_arch_init(void)
 {
        struct pci_mmcfg_region *cfg;
 
-       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
-               cfg->virt = mcfg_ioremap(cfg);
-               if (!cfg->virt) {
-                       printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
-                              &cfg->res);
+       list_for_each_entry(cfg, &pci_mmcfg_list, list)
+               if (pci_mmcfg_arch_map(cfg)) {
                        pci_mmcfg_arch_free();
                        return 0;
                }
-       }
+
        raw_pci_ext_ops = &pci_mmcfg;
+
        return 1;
 }
 
@@ -131,10 +129,26 @@ void __init pci_mmcfg_arch_free(void)
 {
        struct pci_mmcfg_region *cfg;
 
-       list_for_each_entry(cfg, &pci_mmcfg_list, list) {
-               if (cfg->virt) {
-                       iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
-                       cfg->virt = NULL;
-               }
+       list_for_each_entry(cfg, &pci_mmcfg_list, list)
+               pci_mmcfg_arch_unmap(cfg);
+}
+
+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;
        }
 }