aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/pci/mmconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/pci/mmconfig.c')
-rw-r--r--arch/x86_64/pci/mmconfig.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 0847735bb31e..8e05449660fe 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -28,6 +28,39 @@ struct mmcfg_virt {
28}; 28};
29static struct mmcfg_virt *pci_mmcfg_virt; 29static struct mmcfg_virt *pci_mmcfg_virt;
30 30
31static inline int mcfg_broken(void)
32{
33 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[0];
34
35 /* Handle more broken MCFG tables on Asus etc.
36 They only contain a single entry for bus 0-0. Assume
37 this applies to all busses. */
38 if (pci_mmcfg_config_num == 1 &&
39 cfg->pci_segment_group_number == 0 &&
40 (cfg->start_bus_number | cfg->end_bus_number) == 0)
41 return 1;
42 return 0;
43}
44
45static void __iomem *mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
46{
47 void __iomem *addr;
48 u32 size;
49
50 if (mcfg_broken())
51 size = 256 << 20;
52 else
53 size = (cfg->end_bus_number + 1) << 20;
54
55 addr = ioremap_nocache(cfg->base_address, size);
56 if (addr) {
57 printk(KERN_INFO "PCI: Using MMCONFIG at %x - %x\n",
58 cfg->base_address,
59 cfg->base_address + size - 1);
60 }
61 return addr;
62}
63
31static char __iomem *get_virt(unsigned int seg, unsigned bus) 64static char __iomem *get_virt(unsigned int seg, unsigned bus)
32{ 65{
33 int cfg_num = -1; 66 int cfg_num = -1;
@@ -45,13 +78,7 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
45 return pci_mmcfg_virt[cfg_num].virt; 78 return pci_mmcfg_virt[cfg_num].virt;
46 } 79 }
47 80
48 /* Handle more broken MCFG tables on Asus etc. 81 if (mcfg_broken())
49 They only contain a single entry for bus 0-0. Assume
50 this applies to all busses. */
51 cfg = &pci_mmcfg_config[0];
52 if (pci_mmcfg_config_num == 1 &&
53 cfg->pci_segment == 0 &&
54 (cfg->start_bus_number | cfg->end_bus_number) == 0)
55 return pci_mmcfg_virt[0].virt; 82 return pci_mmcfg_virt[0].virt;
56 83
57 /* Fall back to type 0 */ 84 /* Fall back to type 0 */
@@ -145,16 +172,13 @@ int __init pci_mmcfg_arch_init(void)
145 172
146 for (i = 0; i < pci_mmcfg_config_num; ++i) { 173 for (i = 0; i < pci_mmcfg_config_num; ++i) {
147 pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; 174 pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
148 pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address, 175 pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
149 MMCONFIG_APER_MAX);
150 if (!pci_mmcfg_virt[i].virt) { 176 if (!pci_mmcfg_virt[i].virt) {
151 printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " 177 printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
152 "segment %d\n", 178 "segment %d\n",
153 pci_mmcfg_config[i].pci_segment); 179 pci_mmcfg_config[i].pci_segment);
154 return 0; 180 return 0;
155 } 181 }
156 printk(KERN_INFO "PCI: Using MMCONFIG at %Lx\n",
157 pci_mmcfg_config[i].address);
158 } 182 }
159 raw_pci_ops = &pci_mmcfg; 183 raw_pci_ops = &pci_mmcfg;
160 return 1; 184 return 1;