Commit b78673944b22b662b270c8bba5c198f19e4ee4e1

Authored by Olivier Galibert
Committed by Andi Kleen
1 parent 2e188938ab

[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>

Showing 6 changed files with 111 additions and 136 deletions Side-by-side Diff

arch/i386/pci/Makefile
1 1 obj-y := i386.o init.o
2 2  
3 3 obj-$(CONFIG_PCI_BIOS) += pcbios.o
4   -obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
  4 +obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
5 5 obj-$(CONFIG_PCI_DIRECT) += direct.o
6 6  
7 7 pci-y := fixup.o
arch/i386/pci/mmconfig-shared.c
  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 +}
arch/i386/pci/mmconfig.c
... ... @@ -15,21 +15,13 @@
15 15 #include <asm/e820.h>
16 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 18 /* Assume systems with more busses have correct MCFG */
23   -#define MAX_CHECK_BUS 16
24   -
25 19 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
26 20  
27 21 /* The base address of the last MMCONFIG device accessed */
28 22 static u32 mmcfg_last_accessed_device;
29 23 static int mmcfg_last_accessed_cpu;
30 24  
31   -static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
32   -
33 25 /*
34 26 * Functions for accessing PCI configuration space with MMCONFIG accesses
35 27 */
... ... @@ -38,8 +30,8 @@
38 30 int cfg_num = -1;
39 31 struct acpi_mcfg_allocation *cfg;
40 32  
41   - if (seg == 0 && bus < MAX_CHECK_BUS &&
42   - test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
  33 + if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
  34 + test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
43 35 return 0;
44 36  
45 37 while (1) {
46 38  
47 39  
... ... @@ -158,68 +150,10 @@
158 150 .write = pci_mmcfg_write,
159 151 };
160 152  
161   -/* K8 systems have some devices (typically in the builtin northbridge)
162   - that are only accessible using type1
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)
  153 +int __init pci_mmcfg_arch_init(void)
168 154 {
169   - int i, k;
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   -}
196   -
197   -void __init pci_mmcfg_init(int type)
198   -{
199   - if ((pci_probe & PCI_PROBE_MMCONF) == 0)
200   - return;
201   -
202   - acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
203   - if ((pci_mmcfg_config_num == 0) ||
204   - (pci_mmcfg_config == NULL) ||
205   - (pci_mmcfg_config[0].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].address,
211   - pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
212   - E820_RESERVED)) {
213   - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
214   - (unsigned long)pci_mmcfg_config[0].address);
215   - printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
216   - return;
217   - }
218   -
219 155 printk(KERN_INFO "PCI: Using MMCONFIG\n");
220 156 raw_pci_ops = &pci_mmcfg;
221   - pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
222   -
223   - unreachable_devices();
  157 + return 1;
224 158 }
... ... @@ -93,4 +93,11 @@
93 93 extern void pci_pcbios_init(void);
94 94 extern void pci_mmcfg_init(int type);
95 95 extern void pcibios_sort(void);
  96 +
  97 +/* pci-mmconfig.c */
  98 +
  99 +#define PCI_MMCFG_MAX_CHECK_BUS 16
  100 +extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
  101 +
  102 +extern int pci_mmcfg_arch_init(void);
arch/x86_64/pci/Makefile
... ... @@ -11,7 +11,7 @@
11 11 obj-$(CONFIG_ACPI) += acpi.o
12 12 obj-y += legacy.o irq.o common.o early.o
13 13 # mmconfig has a 64bit special
14   -obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
  14 +obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
15 15  
16 16 obj-$(CONFIG_NUMA) += k8-bus.o
17 17  
... ... @@ -24,4 +24,5 @@
24 24 i386-y += ../../i386/pci/i386.o
25 25 init-y += ../../i386/pci/init.o
26 26 early-y += ../../i386/pci/early.o
  27 +mmconfig-shared-y += ../../i386/pci/mmconfig-shared.o
arch/x86_64/pci/mmconfig.c
... ... @@ -19,10 +19,8 @@
19 19  
20 20 /* Verify the first 16 busses. We assume that systems with more busses
21 21 get MCFG right. */
22   -#define MAX_CHECK_BUS 16
  22 +#define PCI_MMCFG_MAX_CHECK_BUS 16
23 23  
24   -static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
25   -
26 24 /* Static virtual mapping of the MMCONFIG aperture */
27 25 struct mmcfg_virt {
28 26 struct acpi_mcfg_allocation *cfg;
... ... @@ -63,8 +61,8 @@
63 61 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
64 62 {
65 63 char __iomem *addr;
66   - if (seg == 0 && bus < MAX_CHECK_BUS &&
67   - test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
  64 + if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
  65 + test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
68 66 return NULL;
69 67 addr = get_virt(seg, bus);
70 68 if (!addr)
71 69  
72 70  
73 71  
74 72  
... ... @@ -135,63 +133,16 @@
135 133 .write = pci_mmcfg_write,
136 134 };
137 135  
138   -/* K8 systems have some devices (typically in the builtin northbridge)
139   - that are only accessible using type1
140   - Normally this can be expressed in the MCFG by not listing them
141   - and assigning suitable _SEGs, but this isn't implemented in some BIOS.
142   - Instead try to discover all devices on bus 0 that are unreachable using MM
143   - and fallback for them. */
144   -static __init void unreachable_devices(void)
  136 +int __init pci_mmcfg_arch_init(void)
145 137 {
146   - int i, k;
147   - /* Use the max bus number from ACPI here? */
148   - for (k = 0; k < MAX_CHECK_BUS; k++) {
149   - for (i = 0; i < 32; i++) {
150   - u32 val1;
151   - char __iomem *addr;
152   -
153   - pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
154   - if (val1 == 0xffffffff)
155   - continue;
156   - addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
157   - if (addr == NULL|| readl(addr) != val1) {
158   - set_bit(i + 32*k, fallback_slots);
159   - printk(KERN_NOTICE "PCI: No mmconfig possible"
160   - " on device %02x:%02x\n", k, i);
161   - }
162   - }
163   - }
164   -}
165   -
166   -void __init pci_mmcfg_init(int type)
167   -{
168 138 int i;
169   -
170   - if ((pci_probe & PCI_PROBE_MMCONF) == 0)
171   - return;
172   -
173   - acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
174   - if ((pci_mmcfg_config_num == 0) ||
175   - (pci_mmcfg_config == NULL) ||
176   - (pci_mmcfg_config[0].address == 0))
177   - return;
178   -
179   - /* Only do this check when type 1 works. If it doesn't work
180   - assume we run on a Mac and always use MCFG */
181   - if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address,
182   - pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
183   - E820_RESERVED)) {
184   - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n",
185   - (unsigned long)pci_mmcfg_config[0].address);
186   - printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
187   - return;
188   - }
189   -
190   - pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
  139 + pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
  140 + pci_mmcfg_config_num, GFP_KERNEL);
191 141 if (pci_mmcfg_virt == NULL) {
192 142 printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
193   - return;
  143 + return 0;
194 144 }
  145 +
195 146 for (i = 0; i < pci_mmcfg_config_num; ++i) {
196 147 pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
197 148 pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address,
198 149  
199 150  
200 151  
... ... @@ -200,15 +151,12 @@
200 151 printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
201 152 "segment %d\n",
202 153 pci_mmcfg_config[i].pci_segment);
203   - return;
  154 + return 0;
204 155 }
205   - printk(KERN_INFO "PCI: Using MMCONFIG at %lx\n",
206   - (unsigned long)pci_mmcfg_config[i].address);
  156 + printk(KERN_INFO "PCI: Using MMCONFIG at %Lx\n",
  157 + pci_mmcfg_config[i].address);
207 158 }
208   -
209   - unreachable_devices();
210   -
211 159 raw_pci_ops = &pci_mmcfg;
212   - pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
  160 + return 1;
213 161 }