diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-02-20 14:13:30 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-20 14:13:30 -0500 |
commit | 5a84d159061d914c8dd4aa372ac6e9529c2be453 (patch) | |
tree | 9b08af78085334af44414adafe0096276f8fe0ff /arch/i386/pci/mmconfig.c | |
parent | e80a0e6e7ccdf64575d4384cb4172860422f5b81 (diff) | |
parent | 7d477a04a619e90ee08724e8f2d8803c6bdfcef8 (diff) |
Merge ARM fixes
Diffstat (limited to 'arch/i386/pci/mmconfig.c')
-rw-r--r-- | arch/i386/pci/mmconfig.c | 102 |
1 files changed, 14 insertions, 88 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index e2616a266e13..bb1afd9e589d 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -15,55 +15,33 @@ | |||
15 | #include <asm/e820.h> | 15 | #include <asm/e820.h> |
16 | #include "pci.h" | 16 | #include "pci.h" |
17 | 17 | ||
18 | /* aperture is up to 256MB but BIOS may reserve less */ | ||
19 | #define MMCONFIG_APER_MIN (2 * 1024*1024) | ||
20 | #define MMCONFIG_APER_MAX (256 * 1024*1024) | ||
21 | |||
22 | /* Assume systems with more busses have correct MCFG */ | 18 | /* Assume systems with more busses have correct MCFG */ |
23 | #define MAX_CHECK_BUS 16 | ||
24 | |||
25 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | 19 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
26 | 20 | ||
27 | /* The base address of the last MMCONFIG device accessed */ | 21 | /* The base address of the last MMCONFIG device accessed */ |
28 | static u32 mmcfg_last_accessed_device; | 22 | static u32 mmcfg_last_accessed_device; |
29 | static int mmcfg_last_accessed_cpu; | 23 | static int mmcfg_last_accessed_cpu; |
30 | 24 | ||
31 | static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32); | ||
32 | |||
33 | /* | 25 | /* |
34 | * Functions for accessing PCI configuration space with MMCONFIG accesses | 26 | * Functions for accessing PCI configuration space with MMCONFIG accesses |
35 | */ | 27 | */ |
36 | static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) | 28 | static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) |
37 | { | 29 | { |
38 | int cfg_num = -1; | 30 | struct acpi_mcfg_allocation *cfg; |
39 | struct acpi_table_mcfg_config *cfg; | 31 | int cfg_num; |
40 | 32 | ||
41 | if (seg == 0 && bus < MAX_CHECK_BUS && | 33 | if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS && |
42 | test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots)) | 34 | test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots)) |
43 | return 0; | 35 | return 0; |
44 | 36 | ||
45 | while (1) { | 37 | for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { |
46 | ++cfg_num; | ||
47 | if (cfg_num >= pci_mmcfg_config_num) { | ||
48 | break; | ||
49 | } | ||
50 | cfg = &pci_mmcfg_config[cfg_num]; | 38 | cfg = &pci_mmcfg_config[cfg_num]; |
51 | if (cfg->pci_segment_group_number != seg) | 39 | if (cfg->pci_segment == seg && |
52 | continue; | 40 | (cfg->start_bus_number <= bus) && |
53 | if ((cfg->start_bus_number <= bus) && | ||
54 | (cfg->end_bus_number >= bus)) | 41 | (cfg->end_bus_number >= bus)) |
55 | return cfg->base_address; | 42 | return cfg->address; |
56 | } | 43 | } |
57 | 44 | ||
58 | /* Handle more broken MCFG tables on Asus etc. | ||
59 | They only contain a single entry for bus 0-0. Assume | ||
60 | this applies to all busses. */ | ||
61 | cfg = &pci_mmcfg_config[0]; | ||
62 | if (pci_mmcfg_config_num == 1 && | ||
63 | cfg->pci_segment_group_number == 0 && | ||
64 | (cfg->start_bus_number | cfg->end_bus_number) == 0) | ||
65 | return cfg->base_address; | ||
66 | |||
67 | /* Fall back to type 0 */ | 45 | /* Fall back to type 0 */ |
68 | return 0; | 46 | return 0; |
69 | } | 47 | } |
@@ -125,7 +103,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | |||
125 | unsigned long flags; | 103 | unsigned long flags; |
126 | u32 base; | 104 | u32 base; |
127 | 105 | ||
128 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) | 106 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) |
129 | return -EINVAL; | 107 | return -EINVAL; |
130 | 108 | ||
131 | base = get_base_addr(seg, bus, devfn); | 109 | base = get_base_addr(seg, bus, devfn); |
@@ -158,67 +136,15 @@ static struct pci_raw_ops pci_mmcfg = { | |||
158 | .write = pci_mmcfg_write, | 136 | .write = pci_mmcfg_write, |
159 | }; | 137 | }; |
160 | 138 | ||
161 | /* K8 systems have some devices (typically in the builtin northbridge) | 139 | int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, |
162 | that are only accessible using type1 | 140 | unsigned int devfn) |
163 | Normally this can be expressed in the MCFG by not listing them | ||
164 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
165 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
166 | and fallback for them. */ | ||
167 | static __init void unreachable_devices(void) | ||
168 | { | 141 | { |
169 | int i, k; | 142 | return get_base_addr(seg, bus, devfn) != 0; |
170 | unsigned long flags; | ||
171 | |||
172 | for (k = 0; k < MAX_CHECK_BUS; k++) { | ||
173 | for (i = 0; i < 32; i++) { | ||
174 | u32 val1; | ||
175 | u32 addr; | ||
176 | |||
177 | pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1); | ||
178 | if (val1 == 0xffffffff) | ||
179 | continue; | ||
180 | |||
181 | /* Locking probably not needed, but safer */ | ||
182 | spin_lock_irqsave(&pci_config_lock, flags); | ||
183 | addr = get_base_addr(0, k, PCI_DEVFN(i, 0)); | ||
184 | if (addr != 0) | ||
185 | pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0)); | ||
186 | if (addr == 0 || | ||
187 | readl((u32 __iomem *)mmcfg_virt_addr) != val1) { | ||
188 | set_bit(i + 32*k, fallback_slots); | ||
189 | printk(KERN_NOTICE | ||
190 | "PCI: No mmconfig possible on %x:%x\n", k, i); | ||
191 | } | ||
192 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
193 | } | ||
194 | } | ||
195 | } | 143 | } |
196 | 144 | ||
197 | void __init pci_mmcfg_init(int type) | 145 | int __init pci_mmcfg_arch_init(void) |
198 | { | 146 | { |
199 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | ||
200 | return; | ||
201 | |||
202 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
203 | if ((pci_mmcfg_config_num == 0) || | ||
204 | (pci_mmcfg_config == NULL) || | ||
205 | (pci_mmcfg_config[0].base_address == 0)) | ||
206 | return; | ||
207 | |||
208 | /* Only do this check when type 1 works. If it doesn't work | ||
209 | assume we run on a Mac and always use MCFG */ | ||
210 | if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
211 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, | ||
212 | E820_RESERVED)) { | ||
213 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", | ||
214 | pci_mmcfg_config[0].base_address); | ||
215 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); | 147 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); |
220 | raw_pci_ops = &pci_mmcfg; | 148 | raw_pci_ops = &pci_mmcfg; |
221 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 149 | return 1; |
222 | |||
223 | unreachable_devices(); | ||
224 | } | 150 | } |