aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@huawei.com>2012-06-22 02:55:13 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-06-22 17:16:31 -0400
commit9cf0105da5a315677d8f91043fb87fdade0d8b39 (patch)
tree85519a44e3c8363bff3ec0f68e0a2fbeb3e75a2b /arch
parent376f70acfe4bd97493299cdfc00a8d235279d267 (diff)
x86/PCI: introduce pci_mmcfg_arch_map()/pci_mmcfg_arch_unmap()
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/pci_x86.h2
-rw-r--r--arch/x86/pci/mmconfig_32.c15
-rw-r--r--arch/x86/pci/mmconfig_64.c38
3 files changed, 43 insertions, 12 deletions
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index b3a531746026..df898ceab4d4 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 {
135 135
136extern int __init pci_mmcfg_arch_init(void); 136extern int __init pci_mmcfg_arch_init(void);
137extern void __init pci_mmcfg_arch_free(void); 137extern void __init pci_mmcfg_arch_free(void);
138extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
139extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
138extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); 140extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
139 141
140extern struct list_head pci_mmcfg_list; 142extern struct list_head pci_mmcfg_list;
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index 5dad04aa6b37..a22785deb50e 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)
141void __init pci_mmcfg_arch_free(void) 141void __init pci_mmcfg_arch_free(void)
142{ 142{
143} 143}
144
145int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
146{
147 return 0;
148}
149
150void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
151{
152 unsigned long flags;
153
154 /* Invalidate the cached mmcfg map entry. */
155 raw_spin_lock_irqsave(&pci_config_lock, flags);
156 mmcfg_last_accessed_device = 0;
157 raw_spin_unlock_irqrestore(&pci_config_lock, flags);
158}
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index acc48c5b6863..ebefea5107a7 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 = {
95 .write = pci_mmcfg_write, 95 .write = pci_mmcfg_write,
96}; 96};
97 97
98static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg) 98static void __iomem * __devinit mcfg_ioremap(struct pci_mmcfg_region *cfg)
99{ 99{
100 void __iomem *addr; 100 void __iomem *addr;
101 u64 start, size; 101 u64 start, size;
@@ -114,16 +114,14 @@ int __init pci_mmcfg_arch_init(void)
114{ 114{
115 struct pci_mmcfg_region *cfg; 115 struct pci_mmcfg_region *cfg;
116 116
117 list_for_each_entry(cfg, &pci_mmcfg_list, list) { 117 list_for_each_entry(cfg, &pci_mmcfg_list, list)
118 cfg->virt = mcfg_ioremap(cfg); 118 if (pci_mmcfg_arch_map(cfg)) {
119 if (!cfg->virt) {
120 printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
121 &cfg->res);
122 pci_mmcfg_arch_free(); 119 pci_mmcfg_arch_free();
123 return 0; 120 return 0;
124 } 121 }
125 } 122
126 raw_pci_ext_ops = &pci_mmcfg; 123 raw_pci_ext_ops = &pci_mmcfg;
124
127 return 1; 125 return 1;
128} 126}
129 127
@@ -131,10 +129,26 @@ void __init pci_mmcfg_arch_free(void)
131{ 129{
132 struct pci_mmcfg_region *cfg; 130 struct pci_mmcfg_region *cfg;
133 131
134 list_for_each_entry(cfg, &pci_mmcfg_list, list) { 132 list_for_each_entry(cfg, &pci_mmcfg_list, list)
135 if (cfg->virt) { 133 pci_mmcfg_arch_unmap(cfg);
136 iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus)); 134}
137 cfg->virt = NULL; 135
138 } 136int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
137{
138 cfg->virt = mcfg_ioremap(cfg);
139 if (!cfg->virt) {
140 printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
141 &cfg->res);
142 return -ENOMEM;
143 }
144
145 return 0;
146}
147
148void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
149{
150 if (cfg && cfg->virt) {
151 iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
152 cfg->virt = NULL;
139 } 153 }
140} 154}