aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci/mmconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/pci/mmconfig.c')
-rw-r--r--arch/i386/pci/mmconfig.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 021a50aa51f4..60f0e7a1162a 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -11,11 +11,9 @@
11 11
12#include <linux/pci.h> 12#include <linux/pci.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/acpi.h>
14#include "pci.h" 15#include "pci.h"
15 16
16/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
17u32 pci_mmcfg_base_addr;
18
19#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) 17#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
20 18
21/* The base address of the last MMCONFIG device accessed */ 19/* The base address of the last MMCONFIG device accessed */
@@ -24,10 +22,31 @@ static u32 mmcfg_last_accessed_device;
24/* 22/*
25 * Functions for accessing PCI configuration space with MMCONFIG accesses 23 * Functions for accessing PCI configuration space with MMCONFIG accesses
26 */ 24 */
25static u32 get_base_addr(unsigned int seg, int bus)
26{
27 int cfg_num = -1;
28 struct acpi_table_mcfg_config *cfg;
29
30 while (1) {
31 ++cfg_num;
32 if (cfg_num >= pci_mmcfg_config_num) {
33 /* something bad is going on, no cfg table is found. */
34 /* so we fall back to the old way we used to do this */
35 /* and just rely on the first entry to be correct. */
36 return pci_mmcfg_config[0].base_address;
37 }
38 cfg = &pci_mmcfg_config[cfg_num];
39 if (cfg->pci_segment_group_number != seg)
40 continue;
41 if ((cfg->start_bus_number <= bus) &&
42 (cfg->end_bus_number >= bus))
43 return cfg->base_address;
44 }
45}
27 46
28static inline void pci_exp_set_dev_base(int bus, int devfn) 47static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn)
29{ 48{
30 u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12); 49 u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12);
31 if (dev_base != mmcfg_last_accessed_device) { 50 if (dev_base != mmcfg_last_accessed_device) {
32 mmcfg_last_accessed_device = dev_base; 51 mmcfg_last_accessed_device = dev_base;
33 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); 52 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
@@ -44,7 +63,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
44 63
45 spin_lock_irqsave(&pci_config_lock, flags); 64 spin_lock_irqsave(&pci_config_lock, flags);
46 65
47 pci_exp_set_dev_base(bus, devfn); 66 pci_exp_set_dev_base(seg, bus, devfn);
48 67
49 switch (len) { 68 switch (len) {
50 case 1: 69 case 1:
@@ -73,7 +92,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
73 92
74 spin_lock_irqsave(&pci_config_lock, flags); 93 spin_lock_irqsave(&pci_config_lock, flags);
75 94
76 pci_exp_set_dev_base(bus, devfn); 95 pci_exp_set_dev_base(seg, bus, devfn);
77 96
78 switch (len) { 97 switch (len) {
79 case 1: 98 case 1:
@@ -101,7 +120,11 @@ static int __init pci_mmcfg_init(void)
101{ 120{
102 if ((pci_probe & PCI_PROBE_MMCONF) == 0) 121 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
103 goto out; 122 goto out;
104 if (!pci_mmcfg_base_addr) 123
124 acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
125 if ((pci_mmcfg_config_num == 0) ||
126 (pci_mmcfg_config == NULL) ||
127 (pci_mmcfg_config[0].base_address == 0))
105 goto out; 128 goto out;
106 129
107 /* Kludge for now. Don't use mmconfig on AMD systems because 130 /* Kludge for now. Don't use mmconfig on AMD systems because