]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/i386/pci/mmconfig-shared.c
[PATCH] mmconfig: fix unreachable_devices()
[mirror_ubuntu-hirsute-kernel.git] / arch / i386 / pci / mmconfig-shared.c
CommitLineData
b7867394
OG
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:
9358c693 6 * - known chipset handling
b7867394
OG
7 * - ACPI decoding and validation
8 *
9 * Per-architecture code takes care of the mappings and accesses
10 * themselves.
11 */
12
13#include <linux/pci.h>
14#include <linux/init.h>
15#include <linux/acpi.h>
16#include <linux/bitmap.h>
17#include <asm/e820.h>
18
19#include "pci.h"
20
21/* aperture is up to 256MB but BIOS may reserve less */
22#define MMCONFIG_APER_MIN (2 * 1024*1024)
23#define MMCONFIG_APER_MAX (256 * 1024*1024)
24
b7867394
OG
25DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
26
27/* K8 systems have some devices (typically in the builtin northbridge)
28 that are only accessible using type1
29 Normally this can be expressed in the MCFG by not listing them
30 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
31 Instead try to discover all devices on bus 0 that are unreachable using MM
32 and fallback for them. */
429d512e 33static void __init unreachable_devices(void)
b7867394 34{
429d512e 35 int i, bus;
b7867394 36 /* Use the max bus number from ACPI here? */
429d512e 37 for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
b7867394 38 for (i = 0; i < 32; i++) {
429d512e 39 unsigned int devfn = PCI_DEVFN(i, 0);
b7867394
OG
40 u32 val1, val2;
41
429d512e 42 pci_conf1_read(0, bus, devfn, 0, 4, &val1);
b7867394
OG
43 if (val1 == 0xffffffff)
44 continue;
45
56829d19
OH
46 if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
47 raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
48 if (val1 == val2)
49 continue;
b7867394 50 }
56829d19
OH
51 set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
52 printk(KERN_NOTICE "PCI: No mmconfig possible on device"
53 " %02x:%02x\n", bus, i);
b7867394
OG
54 }
55 }
56}
57
429d512e 58static const char __init *pci_mmcfg_e7520(void)
9358c693
OG
59{
60 u32 win;
61 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
62
63 pci_mmcfg_config_num = 1;
64 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
65 if (!pci_mmcfg_config)
66 return NULL;
67 pci_mmcfg_config[0].address = (win & 0xf000) << 16;
68 pci_mmcfg_config[0].pci_segment = 0;
69 pci_mmcfg_config[0].start_bus_number = 0;
70 pci_mmcfg_config[0].end_bus_number = 255;
71
72 return "Intel Corporation E7520 Memory Controller Hub";
73}
74
429d512e 75static const char __init *pci_mmcfg_intel_945(void)
9358c693
OG
76{
77 u32 pciexbar, mask = 0, len = 0;
78
79 pci_mmcfg_config_num = 1;
80
81 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
82
83 /* Enable bit */
84 if (!(pciexbar & 1))
85 pci_mmcfg_config_num = 0;
86
87 /* Size bits */
88 switch ((pciexbar >> 1) & 3) {
89 case 0:
90 mask = 0xf0000000U;
91 len = 0x10000000U;
92 break;
93 case 1:
94 mask = 0xf8000000U;
95 len = 0x08000000U;
96 break;
97 case 2:
98 mask = 0xfc000000U;
99 len = 0x04000000U;
100 break;
101 default:
102 pci_mmcfg_config_num = 0;
103 }
104
105 /* Errata #2, things break when not aligned on a 256Mb boundary */
106 /* Can only happen in 64M/128M mode */
107
108 if ((pciexbar & mask) & 0x0fffffffU)
109 pci_mmcfg_config_num = 0;
110
111 if (pci_mmcfg_config_num) {
112 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL);
113 if (!pci_mmcfg_config)
114 return NULL;
115 pci_mmcfg_config[0].address = pciexbar & mask;
116 pci_mmcfg_config[0].pci_segment = 0;
117 pci_mmcfg_config[0].start_bus_number = 0;
118 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
119 }
120
121 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
122}
123
124struct pci_mmcfg_hostbridge_probe {
125 u32 vendor;
126 u32 device;
127 const char *(*probe)(void);
128};
129
429d512e 130static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
9358c693
OG
131 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
132 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
133};
134
135static int __init pci_mmcfg_check_hostbridge(void)
136{
137 u32 l;
138 u16 vendor, device;
139 int i;
140 const char *name;
141
142 pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
143 vendor = l & 0xffff;
144 device = (l >> 16) & 0xffff;
145
146 pci_mmcfg_config_num = 0;
147 pci_mmcfg_config = NULL;
148 name = NULL;
149
429d512e
OH
150 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
151 if (pci_mmcfg_probes[i].vendor == vendor &&
152 pci_mmcfg_probes[i].device == device)
9358c693 153 name = pci_mmcfg_probes[i].probe();
429d512e 154 }
9358c693
OG
155
156 if (name) {
429d512e
OH
157 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
158 name, pci_mmcfg_config_num ? "with" : "without");
9358c693
OG
159 }
160
161 return name != NULL;
162}
163
429d512e 164static void __init pci_mmcfg_insert_resources(void)
6a0668fc
OG
165{
166#define PCI_MMCFG_RESOURCE_NAME_LEN 19
167 int i;
168 struct resource *res;
169 char *names;
170 unsigned num_buses;
171
172 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res),
173 pci_mmcfg_config_num, GFP_KERNEL);
6a0668fc
OG
174 if (!res) {
175 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n");
176 return;
177 }
178
179 names = (void *)&res[pci_mmcfg_config_num];
180 for (i = 0; i < pci_mmcfg_config_num; i++, res++) {
429d512e
OH
181 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i];
182 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1;
6a0668fc
OG
183 res->name = names;
184 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
429d512e
OH
185 cfg->pci_segment);
186 res->start = cfg->address;
6a0668fc
OG
187 res->end = res->start + (num_buses << 20) - 1;
188 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
189 insert_resource(&iomem_resource, res);
190 names += PCI_MMCFG_RESOURCE_NAME_LEN;
191 }
192}
193
44de0203
OH
194static void __init pci_mmcfg_reject_broken(void)
195{
196 typeof(pci_mmcfg_config[0]) *cfg = &pci_mmcfg_config[0];
197
198 /*
199 * Handle more broken MCFG tables on Asus etc.
200 * They only contain a single entry for bus 0-0.
201 */
202 if (pci_mmcfg_config_num == 1 &&
203 cfg->pci_segment == 0 &&
204 (cfg->start_bus_number | cfg->end_bus_number) == 0) {
205 kfree(pci_mmcfg_config);
206 pci_mmcfg_config = NULL;
207 pci_mmcfg_config_num = 0;
208
209 printk(KERN_ERR "PCI: start and end of bus number is 0. "
210 "Rejected as broken MCFG.");
211 }
212}
213
b7867394
OG
214void __init pci_mmcfg_init(int type)
215{
9358c693
OG
216 int known_bridge = 0;
217
b7867394
OG
218 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
219 return;
220
9358c693
OG
221 if (type == 1 && pci_mmcfg_check_hostbridge())
222 known_bridge = 1;
223
44de0203 224 if (!known_bridge) {
9358c693 225 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
44de0203
OH
226 pci_mmcfg_reject_broken();
227 }
b7867394
OG
228
229 if ((pci_mmcfg_config_num == 0) ||
230 (pci_mmcfg_config == NULL) ||
231 (pci_mmcfg_config[0].address == 0))
232 return;
233
234 /* Only do this check when type 1 works. If it doesn't work
235 assume we run on a Mac and always use MCFG */
9358c693 236 if (type == 1 && !known_bridge &&
b7867394
OG
237 !e820_all_mapped(pci_mmcfg_config[0].address,
238 pci_mmcfg_config[0].address + MMCONFIG_APER_MIN,
239 E820_RESERVED)) {
240 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not E820-reserved\n",
241 pci_mmcfg_config[0].address);
242 printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
243 return;
244 }
245
246 if (pci_mmcfg_arch_init()) {
5f027387
OG
247 if (type == 1)
248 unreachable_devices();
6a0668fc
OG
249 if (known_bridge)
250 pci_mmcfg_insert_resources();
b7867394
OG
251 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
252 }
253}