diff options
author | Olivier Galibert <galibert@pobox.com> | 2007-02-13 07:26:20 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-02-13 07:26:20 -0500 |
commit | b78673944b22b662b270c8bba5c198f19e4ee4e1 (patch) | |
tree | 3cbbe3808335fc297fb3daf01dcbf26d4243a2db /arch/i386/pci/mmconfig-shared.c | |
parent | 2e188938ab2358034801938c2329b016ca135823 (diff) |
[PATCH] mmconfig: Share parts of mmconfig code between i386 and x86-64
i386 and x86-64 pci mmconfig code have a lot in common. So share what's
shareable between the two.
Signed-off-by: Olivier Galibert <galibert@pobox.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'arch/i386/pci/mmconfig-shared.c')
-rw-r--r-- | arch/i386/pci/mmconfig-shared.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/arch/i386/pci/mmconfig-shared.c b/arch/i386/pci/mmconfig-shared.c new file mode 100644 index 000000000000..998e04f6d68f --- /dev/null +++ b/arch/i386/pci/mmconfig-shared.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * mmconfig-shared.c - Low-level direct PCI config space access via | ||
3 | * MMCONFIG - common code between i386 and x86-64. | ||
4 | * | ||
5 | * This code does: | ||
6 | * - ACPI decoding and validation | ||
7 | * | ||
8 | * Per-architecture code takes care of the mappings and accesses | ||
9 | * themselves. | ||
10 | */ | ||
11 | |||
12 | #include <linux/pci.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/bitmap.h> | ||
16 | #include <asm/e820.h> | ||
17 | |||
18 | #include "pci.h" | ||
19 | |||
20 | /* aperture is up to 256MB but BIOS may reserve less */ | ||
21 | #define MMCONFIG_APER_MIN (2 * 1024*1024) | ||
22 | #define MMCONFIG_APER_MAX (256 * 1024*1024) | ||
23 | |||
24 | /* Verify the first 16 busses. We assume that systems with more busses | ||
25 | get MCFG right. */ | ||
26 | #define PCI_MMCFG_MAX_CHECK_BUS 16 | ||
27 | |||
28 | DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS); | ||
29 | |||
30 | /* K8 systems have some devices (typically in the builtin northbridge) | ||
31 | that are only accessible using type1 | ||
32 | Normally this can be expressed in the MCFG by not listing them | ||
33 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
34 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
35 | and fallback for them. */ | ||
36 | static __init void unreachable_devices(void) | ||
37 | { | ||
38 | int i, k; | ||
39 | /* Use the max bus number from ACPI here? */ | ||
40 | for (k = 0; k < PCI_MMCFG_MAX_CHECK_BUS; k++) { | ||
41 | for (i = 0; i < 32; i++) { | ||
42 | u32 val1, val2; | ||
43 | |||
44 | pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1); | ||
45 | if (val1 == 0xffffffff) | ||
46 | continue; | ||
47 | |||
48 | raw_pci_ops->read(0, k, PCI_DEVFN(i, 0), 0, 4, &val2); | ||
49 | if (val1 != val2) { | ||
50 | set_bit(i + 32*k, pci_mmcfg_fallback_slots); | ||
51 | printk(KERN_NOTICE "PCI: No mmconfig possible" | ||
52 | " on device %02x:%02x\n", k, i); | ||
53 | } | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | |||
58 | void __init pci_mmcfg_init(int type) | ||
59 | { | ||
60 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | ||
61 | return; | ||
62 | |||
63 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
64 | |||
65 | if ((pci_mmcfg_config_num == 0) || | ||
66 | (pci_mmcfg_config == NULL) || | ||
67 | (pci_mmcfg_config[0].address == 0)) | ||
68 | return; | ||
69 | |||
70 | /* Only do this check when type 1 works. If it doesn't work | ||
71 | assume we run on a Mac and always use MCFG */ | ||
72 | if (type == 1 && | ||
73 | !e820_all_mapped(pci_mmcfg_config[0].address, | ||
74 | pci_mmcfg_config[0].address + MMCONFIG_APER_MIN, | ||
75 | E820_RESERVED)) { | ||
76 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not E820-reserved\n", | ||
77 | pci_mmcfg_config[0].address); | ||
78 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | if (pci_mmcfg_arch_init()) { | ||
83 | unreachable_devices(); | ||
84 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | ||
85 | } | ||
86 | } | ||