Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Low-Level PCI Support for PC
4 : : *
5 : : * (c) 1999--2000 Martin Mares <mj@ucw.cz>
6 : : */
7 : :
8 : : #include <linux/sched.h>
9 : : #include <linux/pci.h>
10 : : #include <linux/pci-acpi.h>
11 : : #include <linux/ioport.h>
12 : : #include <linux/init.h>
13 : : #include <linux/dmi.h>
14 : : #include <linux/slab.h>
15 : :
16 : : #include <asm/acpi.h>
17 : : #include <asm/segment.h>
18 : : #include <asm/io.h>
19 : : #include <asm/smp.h>
20 : : #include <asm/pci_x86.h>
21 : : #include <asm/setup.h>
22 : :
23 : : unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
24 : : PCI_PROBE_MMCONF;
25 : :
26 : : static int pci_bf_sort;
27 : : int pci_routeirq;
28 : : int noioapicquirk;
29 : : #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
30 : : int noioapicreroute = 0;
31 : : #else
32 : : int noioapicreroute = 1;
33 : : #endif
34 : : int pcibios_last_bus = -1;
35 : : unsigned long pirq_table_addr;
36 : : const struct pci_raw_ops *__read_mostly raw_pci_ops;
37 : : const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
38 : :
39 : 6630 : int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
40 : : int reg, int len, u32 *val)
41 : : {
42 [ + + + - ]: 6630 : if (domain == 0 && reg < 256 && raw_pci_ops)
43 : 6617 : return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
44 [ - + ]: 13 : if (raw_pci_ext_ops)
45 : 0 : return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
46 : : return -EINVAL;
47 : : }
48 : :
49 : 2899 : int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
50 : : int reg, int len, u32 val)
51 : : {
52 [ + - + - ]: 2899 : if (domain == 0 && reg < 256 && raw_pci_ops)
53 : 2899 : return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
54 [ # # ]: 0 : if (raw_pci_ext_ops)
55 : 0 : return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
56 : : return -EINVAL;
57 : : }
58 : :
59 : 6058 : static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
60 : : {
61 : 6058 : return raw_pci_read(pci_domain_nr(bus), bus->number,
62 : : devfn, where, size, value);
63 : : }
64 : :
65 : 2834 : static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
66 : : {
67 : 2834 : return raw_pci_write(pci_domain_nr(bus), bus->number,
68 : : devfn, where, size, value);
69 : : }
70 : :
71 : : struct pci_ops pci_root_ops = {
72 : : .read = pci_read,
73 : : .write = pci_write,
74 : : };
75 : :
76 : : /*
77 : : * This interrupt-safe spinlock protects all accesses to PCI configuration
78 : : * space, except for the mmconfig (ECAM) based operations.
79 : : */
80 : : DEFINE_RAW_SPINLOCK(pci_config_lock);
81 : :
82 : 0 : static int __init can_skip_ioresource_align(const struct dmi_system_id *d)
83 : : {
84 : 0 : pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
85 : 0 : printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
86 : 0 : return 0;
87 : : }
88 : :
89 : : static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __initconst = {
90 : : /*
91 : : * Systems where PCI IO resource ISA alignment can be skipped
92 : : * when the ISA enable bit in the bridge control is not set
93 : : */
94 : : {
95 : : .callback = can_skip_ioresource_align,
96 : : .ident = "IBM System x3800",
97 : : .matches = {
98 : : DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
99 : : DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
100 : : },
101 : : },
102 : : {
103 : : .callback = can_skip_ioresource_align,
104 : : .ident = "IBM System x3850",
105 : : .matches = {
106 : : DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
107 : : DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
108 : : },
109 : : },
110 : : {
111 : : .callback = can_skip_ioresource_align,
112 : : .ident = "IBM System x3950",
113 : : .matches = {
114 : : DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
115 : : DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
116 : : },
117 : : },
118 : : {}
119 : : };
120 : :
121 : 13 : void __init dmi_check_skip_isa_align(void)
122 : : {
123 : 13 : dmi_check_system(can_skip_pciprobe_dmi_table);
124 : 13 : }
125 : :
126 : 91 : static void pcibios_fixup_device_resources(struct pci_dev *dev)
127 : : {
128 : 91 : struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
129 : 91 : struct resource *bar_r;
130 : 91 : int bar;
131 : :
132 [ - + ]: 91 : if (pci_probe & PCI_NOASSIGN_BARS) {
133 : : /*
134 : : * If the BIOS did not assign the BAR, zero out the
135 : : * resource so the kernel doesn't attempt to assign
136 : : * it later on in pci_assign_unassigned_resources
137 : : */
138 [ # # ]: 0 : for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
139 : 0 : bar_r = &dev->resource[bar];
140 [ # # # # ]: 0 : if (bar_r->start == 0 && bar_r->end != 0) {
141 : 0 : bar_r->flags = 0;
142 : 0 : bar_r->end = 0;
143 : : }
144 : : }
145 : : }
146 : :
147 [ - + ]: 91 : if (pci_probe & PCI_NOASSIGN_ROMS) {
148 [ # # ]: 0 : if (rom_r->parent)
149 : : return;
150 [ # # ]: 0 : if (rom_r->start) {
151 : : /* we deal with BIOS assigned ROM later */
152 : : return;
153 : : }
154 : 0 : rom_r->start = rom_r->end = rom_r->flags = 0;
155 : : }
156 : : }
157 : :
158 : : /*
159 : : * Called after each bus is probed, but before its children
160 : : * are examined.
161 : : */
162 : :
163 : 13 : void pcibios_fixup_bus(struct pci_bus *b)
164 : : {
165 : 13 : struct pci_dev *dev;
166 : :
167 : 13 : pci_read_bridge_bases(b);
168 [ + + ]: 104 : list_for_each_entry(dev, &b->devices, bus_list)
169 : 91 : pcibios_fixup_device_resources(dev);
170 : 13 : }
171 : :
172 : 13 : void pcibios_add_bus(struct pci_bus *bus)
173 : : {
174 : 13 : acpi_pci_add_bus(bus);
175 : 13 : }
176 : :
177 : 0 : void pcibios_remove_bus(struct pci_bus *bus)
178 : : {
179 : 0 : acpi_pci_remove_bus(bus);
180 : 0 : }
181 : :
182 : : /*
183 : : * Only use DMI information to set this if nothing was passed
184 : : * on the kernel command line (which was parsed earlier).
185 : : */
186 : :
187 : 0 : static int __init set_bf_sort(const struct dmi_system_id *d)
188 : : {
189 [ # # ]: 0 : if (pci_bf_sort == pci_bf_sort_default) {
190 : 0 : pci_bf_sort = pci_dmi_bf;
191 : 0 : printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
192 : : }
193 : 0 : return 0;
194 : : }
195 : :
196 : 0 : static void __init read_dmi_type_b1(const struct dmi_header *dm,
197 : : void *private_data)
198 : : {
199 : 0 : u8 *data = (u8 *)dm + 4;
200 : :
201 [ # # ]: 0 : if (dm->type != 0xB1)
202 : : return;
203 [ # # ]: 0 : if ((((*(u32 *)data) >> 9) & 0x03) == 0x01)
204 : 0 : set_bf_sort((const struct dmi_system_id *)private_data);
205 : : }
206 : :
207 : 0 : static int __init find_sort_method(const struct dmi_system_id *d)
208 : : {
209 : 0 : dmi_walk(read_dmi_type_b1, (void *)d);
210 : 0 : return 0;
211 : : }
212 : :
213 : : /*
214 : : * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
215 : : */
216 : : #ifdef __i386__
217 : : static int __init assign_all_busses(const struct dmi_system_id *d)
218 : : {
219 : : pci_probe |= PCI_ASSIGN_ALL_BUSSES;
220 : : printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
221 : : " (pci=assign-busses)\n", d->ident);
222 : : return 0;
223 : : }
224 : : #endif
225 : :
226 : 0 : static int __init set_scan_all(const struct dmi_system_id *d)
227 : : {
228 : 0 : printk(KERN_INFO "PCI: %s detected, enabling pci=pcie_scan_all\n",
229 : : d->ident);
230 : 0 : pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
231 : 0 : return 0;
232 : : }
233 : :
234 : : static const struct dmi_system_id pciprobe_dmi_table[] __initconst = {
235 : : #ifdef __i386__
236 : : /*
237 : : * Laptops which need pci=assign-busses to see Cardbus cards
238 : : */
239 : : {
240 : : .callback = assign_all_busses,
241 : : .ident = "Samsung X20 Laptop",
242 : : .matches = {
243 : : DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
244 : : DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
245 : : },
246 : : },
247 : : #endif /* __i386__ */
248 : : {
249 : : .callback = set_bf_sort,
250 : : .ident = "Dell PowerEdge 1950",
251 : : .matches = {
252 : : DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
253 : : DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
254 : : },
255 : : },
256 : : {
257 : : .callback = set_bf_sort,
258 : : .ident = "Dell PowerEdge 1955",
259 : : .matches = {
260 : : DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
261 : : DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
262 : : },
263 : : },
264 : : {
265 : : .callback = set_bf_sort,
266 : : .ident = "Dell PowerEdge 2900",
267 : : .matches = {
268 : : DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
269 : : DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
270 : : },
271 : : },
272 : : {
273 : : .callback = set_bf_sort,
274 : : .ident = "Dell PowerEdge 2950",
275 : : .matches = {
276 : : DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
277 : : DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
278 : : },
279 : : },
280 : : {
281 : : .callback = set_bf_sort,
282 : : .ident = "Dell PowerEdge R900",
283 : : .matches = {
284 : : DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
285 : : DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
286 : : },
287 : : },
288 : : {
289 : : .callback = find_sort_method,
290 : : .ident = "Dell System",
291 : : .matches = {
292 : : DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
293 : : },
294 : : },
295 : : {
296 : : .callback = set_bf_sort,
297 : : .ident = "HP ProLiant BL20p G3",
298 : : .matches = {
299 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
300 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
301 : : },
302 : : },
303 : : {
304 : : .callback = set_bf_sort,
305 : : .ident = "HP ProLiant BL20p G4",
306 : : .matches = {
307 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
308 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
309 : : },
310 : : },
311 : : {
312 : : .callback = set_bf_sort,
313 : : .ident = "HP ProLiant BL30p G1",
314 : : .matches = {
315 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
316 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
317 : : },
318 : : },
319 : : {
320 : : .callback = set_bf_sort,
321 : : .ident = "HP ProLiant BL25p G1",
322 : : .matches = {
323 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
324 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
325 : : },
326 : : },
327 : : {
328 : : .callback = set_bf_sort,
329 : : .ident = "HP ProLiant BL35p G1",
330 : : .matches = {
331 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
332 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
333 : : },
334 : : },
335 : : {
336 : : .callback = set_bf_sort,
337 : : .ident = "HP ProLiant BL45p G1",
338 : : .matches = {
339 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
340 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
341 : : },
342 : : },
343 : : {
344 : : .callback = set_bf_sort,
345 : : .ident = "HP ProLiant BL45p G2",
346 : : .matches = {
347 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
348 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
349 : : },
350 : : },
351 : : {
352 : : .callback = set_bf_sort,
353 : : .ident = "HP ProLiant BL460c G1",
354 : : .matches = {
355 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
356 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
357 : : },
358 : : },
359 : : {
360 : : .callback = set_bf_sort,
361 : : .ident = "HP ProLiant BL465c G1",
362 : : .matches = {
363 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
364 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
365 : : },
366 : : },
367 : : {
368 : : .callback = set_bf_sort,
369 : : .ident = "HP ProLiant BL480c G1",
370 : : .matches = {
371 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
372 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
373 : : },
374 : : },
375 : : {
376 : : .callback = set_bf_sort,
377 : : .ident = "HP ProLiant BL685c G1",
378 : : .matches = {
379 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
380 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
381 : : },
382 : : },
383 : : {
384 : : .callback = set_bf_sort,
385 : : .ident = "HP ProLiant DL360",
386 : : .matches = {
387 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
388 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"),
389 : : },
390 : : },
391 : : {
392 : : .callback = set_bf_sort,
393 : : .ident = "HP ProLiant DL380",
394 : : .matches = {
395 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
396 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"),
397 : : },
398 : : },
399 : : #ifdef __i386__
400 : : {
401 : : .callback = assign_all_busses,
402 : : .ident = "Compaq EVO N800c",
403 : : .matches = {
404 : : DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
405 : : DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"),
406 : : },
407 : : },
408 : : #endif
409 : : {
410 : : .callback = set_bf_sort,
411 : : .ident = "HP ProLiant DL385 G2",
412 : : .matches = {
413 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
414 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"),
415 : : },
416 : : },
417 : : {
418 : : .callback = set_bf_sort,
419 : : .ident = "HP ProLiant DL585 G2",
420 : : .matches = {
421 : : DMI_MATCH(DMI_SYS_VENDOR, "HP"),
422 : : DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
423 : : },
424 : : },
425 : : {
426 : : .callback = set_scan_all,
427 : : .ident = "Stratus/NEC ftServer",
428 : : .matches = {
429 : : DMI_MATCH(DMI_SYS_VENDOR, "Stratus"),
430 : : DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"),
431 : : },
432 : : },
433 : : {
434 : : .callback = set_scan_all,
435 : : .ident = "Stratus/NEC ftServer",
436 : : .matches = {
437 : : DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
438 : : DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R32"),
439 : : },
440 : : },
441 : : {
442 : : .callback = set_scan_all,
443 : : .ident = "Stratus/NEC ftServer",
444 : : .matches = {
445 : : DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
446 : : DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R31"),
447 : : },
448 : : },
449 : : {}
450 : : };
451 : :
452 : 13 : void __init dmi_check_pciprobe(void)
453 : : {
454 : 13 : dmi_check_system(pciprobe_dmi_table);
455 : 13 : }
456 : :
457 : 0 : void pcibios_scan_root(int busnum)
458 : : {
459 : 0 : struct pci_bus *bus;
460 : 0 : struct pci_sysdata *sd;
461 : 0 : LIST_HEAD(resources);
462 : :
463 : 0 : sd = kzalloc(sizeof(*sd), GFP_KERNEL);
464 [ # # ]: 0 : if (!sd) {
465 : 0 : printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum);
466 : 0 : return;
467 : : }
468 : 0 : sd->node = x86_pci_root_bus_node(busnum);
469 : 0 : x86_pci_root_bus_resources(busnum, &resources);
470 : 0 : printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
471 : 0 : bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
472 [ # # ]: 0 : if (!bus) {
473 : 0 : pci_free_resource_list(&resources);
474 : 0 : kfree(sd);
475 : 0 : return;
476 : : }
477 : 0 : pci_bus_add_devices(bus);
478 : : }
479 : :
480 : 13 : void __init pcibios_set_cache_line_size(void)
481 : : {
482 : 13 : struct cpuinfo_x86 *c = &boot_cpu_data;
483 : :
484 : : /*
485 : : * Set PCI cacheline size to that of the CPU if the CPU has reported it.
486 : : * (For older CPUs that don't support cpuid, we se it to 32 bytes
487 : : * It's also good for 386/486s (which actually have 16)
488 : : * as quite a few PCI devices do not support smaller values.
489 : : */
490 [ + - ]: 13 : if (c->x86_clflush_size > 0) {
491 : 13 : pci_dfl_cache_line_size = c->x86_clflush_size >> 2;
492 : 13 : printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n",
493 : : pci_dfl_cache_line_size << 2);
494 : : } else {
495 : 0 : pci_dfl_cache_line_size = 32 >> 2;
496 : 0 : printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n");
497 : : }
498 : 13 : }
499 : :
500 : 13 : int __init pcibios_init(void)
501 : : {
502 [ - + - - ]: 13 : if (!raw_pci_ops && !raw_pci_ext_ops) {
503 : 0 : printk(KERN_WARNING "PCI: System does not support PCI\n");
504 : 0 : return 0;
505 : : }
506 : :
507 : 13 : pcibios_set_cache_line_size();
508 : 13 : pcibios_resource_survey();
509 : :
510 [ - + ]: 13 : if (pci_bf_sort >= pci_force_bf)
511 : 0 : pci_sort_breadthfirst();
512 : : return 0;
513 : : }
514 : :
515 : 0 : char *__init pcibios_setup(char *str)
516 : : {
517 [ # # ]: 0 : if (!strcmp(str, "off")) {
518 : 0 : pci_probe = 0;
519 : 0 : return NULL;
520 [ # # ]: 0 : } else if (!strcmp(str, "bfsort")) {
521 : 0 : pci_bf_sort = pci_force_bf;
522 : 0 : return NULL;
523 [ # # ]: 0 : } else if (!strcmp(str, "nobfsort")) {
524 : 0 : pci_bf_sort = pci_force_nobf;
525 : 0 : return NULL;
526 : : }
527 : : #ifdef CONFIG_PCI_BIOS
528 : : else if (!strcmp(str, "bios")) {
529 : : pci_probe = PCI_PROBE_BIOS;
530 : : return NULL;
531 : : } else if (!strcmp(str, "nobios")) {
532 : : pci_probe &= ~PCI_PROBE_BIOS;
533 : : return NULL;
534 : : } else if (!strcmp(str, "biosirq")) {
535 : : pci_probe |= PCI_BIOS_IRQ_SCAN;
536 : : return NULL;
537 : : } else if (!strncmp(str, "pirqaddr=", 9)) {
538 : : pirq_table_addr = simple_strtoul(str+9, NULL, 0);
539 : : return NULL;
540 : : }
541 : : #endif
542 : : #ifdef CONFIG_PCI_DIRECT
543 [ # # ]: 0 : else if (!strcmp(str, "conf1")) {
544 : 0 : pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
545 : 0 : return NULL;
546 : : }
547 [ # # ]: 0 : else if (!strcmp(str, "conf2")) {
548 : 0 : pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
549 : 0 : return NULL;
550 : : }
551 : : #endif
552 : : #ifdef CONFIG_PCI_MMCONFIG
553 [ # # ]: 0 : else if (!strcmp(str, "nommconf")) {
554 : 0 : pci_probe &= ~PCI_PROBE_MMCONF;
555 : 0 : return NULL;
556 : : }
557 [ # # ]: 0 : else if (!strcmp(str, "check_enable_amd_mmconf")) {
558 : 0 : pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
559 : 0 : return NULL;
560 : : }
561 : : #endif
562 [ # # ]: 0 : else if (!strcmp(str, "noacpi")) {
563 : 0 : acpi_noirq_set();
564 : 0 : return NULL;
565 : : }
566 [ # # ]: 0 : else if (!strcmp(str, "noearly")) {
567 : 0 : pci_probe |= PCI_PROBE_NOEARLY;
568 : 0 : return NULL;
569 : : }
570 [ # # ]: 0 : else if (!strcmp(str, "usepirqmask")) {
571 : 0 : pci_probe |= PCI_USE_PIRQ_MASK;
572 : 0 : return NULL;
573 [ # # ]: 0 : } else if (!strncmp(str, "irqmask=", 8)) {
574 : 0 : pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
575 : 0 : return NULL;
576 [ # # ]: 0 : } else if (!strncmp(str, "lastbus=", 8)) {
577 : 0 : pcibios_last_bus = simple_strtol(str+8, NULL, 0);
578 : 0 : return NULL;
579 [ # # ]: 0 : } else if (!strcmp(str, "rom")) {
580 : 0 : pci_probe |= PCI_ASSIGN_ROMS;
581 : 0 : return NULL;
582 [ # # ]: 0 : } else if (!strcmp(str, "norom")) {
583 : 0 : pci_probe |= PCI_NOASSIGN_ROMS;
584 : 0 : return NULL;
585 [ # # ]: 0 : } else if (!strcmp(str, "nobar")) {
586 : 0 : pci_probe |= PCI_NOASSIGN_BARS;
587 : 0 : return NULL;
588 [ # # ]: 0 : } else if (!strcmp(str, "assign-busses")) {
589 : 0 : pci_probe |= PCI_ASSIGN_ALL_BUSSES;
590 : 0 : return NULL;
591 [ # # ]: 0 : } else if (!strcmp(str, "use_crs")) {
592 : 0 : pci_probe |= PCI_USE__CRS;
593 : 0 : return NULL;
594 [ # # ]: 0 : } else if (!strcmp(str, "nocrs")) {
595 : 0 : pci_probe |= PCI_ROOT_NO_CRS;
596 : 0 : return NULL;
597 : : #ifdef CONFIG_PHYS_ADDR_T_64BIT
598 [ # # ]: 0 : } else if (!strcmp(str, "big_root_window")) {
599 : 0 : pci_probe |= PCI_BIG_ROOT_WINDOW;
600 : 0 : return NULL;
601 : : #endif
602 [ # # ]: 0 : } else if (!strcmp(str, "routeirq")) {
603 : 0 : pci_routeirq = 1;
604 : 0 : return NULL;
605 [ # # ]: 0 : } else if (!strcmp(str, "skip_isa_align")) {
606 : 0 : pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
607 : 0 : return NULL;
608 [ # # ]: 0 : } else if (!strcmp(str, "noioapicquirk")) {
609 : 0 : noioapicquirk = 1;
610 : 0 : return NULL;
611 [ # # ]: 0 : } else if (!strcmp(str, "ioapicreroute")) {
612 [ # # ]: 0 : if (noioapicreroute != -1)
613 : 0 : noioapicreroute = 0;
614 : 0 : return NULL;
615 [ # # ]: 0 : } else if (!strcmp(str, "noioapicreroute")) {
616 [ # # ]: 0 : if (noioapicreroute != -1)
617 : 0 : noioapicreroute = 1;
618 : 0 : return NULL;
619 : : }
620 : : return str;
621 : : }
622 : :
623 : 0 : unsigned int pcibios_assign_all_busses(void)
624 : : {
625 : 0 : return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
626 : : }
627 : :
628 : : static void set_dev_domain_options(struct pci_dev *pdev)
629 : : {
630 : : if (is_vmd(pdev->bus))
631 : : pdev->hotplug_user_indicators = 1;
632 : : }
633 : :
634 : 91 : int pcibios_add_device(struct pci_dev *dev)
635 : : {
636 : 91 : struct setup_data *data;
637 : 91 : struct pci_setup_rom *rom;
638 : 91 : u64 pa_data;
639 : :
640 : 91 : pa_data = boot_params.hdr.setup_data;
641 [ - + ]: 91 : while (pa_data) {
642 : 0 : data = memremap(pa_data, sizeof(*rom), MEMREMAP_WB);
643 [ # # ]: 0 : if (!data)
644 : : return -ENOMEM;
645 : :
646 [ # # ]: 0 : if (data->type == SETUP_PCI) {
647 : 0 : rom = (struct pci_setup_rom *)data;
648 : :
649 [ # # ]: 0 : if ((pci_domain_nr(dev->bus) == rom->segment) &&
650 [ # # ]: 0 : (dev->bus->number == rom->bus) &&
651 [ # # ]: 0 : (PCI_SLOT(dev->devfn) == rom->device) &&
652 [ # # ]: 0 : (PCI_FUNC(dev->devfn) == rom->function) &&
653 [ # # ]: 0 : (dev->vendor == rom->vendor) &&
654 : : (dev->device == rom->devid)) {
655 : 0 : dev->rom = pa_data +
656 : : offsetof(struct pci_setup_rom, romdata);
657 : 0 : dev->romlen = rom->pcilen;
658 : : }
659 : : }
660 : 0 : pa_data = data->next;
661 : 0 : memunmap(data);
662 : : }
663 : : set_dev_domain_options(dev);
664 : : return 0;
665 : : }
666 : :
667 : 52 : int pcibios_enable_device(struct pci_dev *dev, int mask)
668 : : {
669 : 52 : int err;
670 : :
671 [ + - ]: 52 : if ((err = pci_enable_resources(dev, mask)) < 0)
672 : : return err;
673 : :
674 [ + - ]: 52 : if (!pci_dev_msi_enabled(dev))
675 : 52 : return pcibios_enable_irq(dev);
676 : : return 0;
677 : : }
678 : :
679 : 26 : void pcibios_disable_device (struct pci_dev *dev)
680 : : {
681 [ - - + - : 26 : if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+ - ]
682 : 26 : pcibios_disable_irq(dev);
683 : 26 : }
684 : :
685 : : #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
686 : 0 : void pcibios_release_device(struct pci_dev *dev)
687 : : {
688 [ # # ]: 0 : if (atomic_dec_return(&dev->enable_cnt) >= 0)
689 [ # # ]: 0 : pcibios_disable_device(dev);
690 : :
691 : 0 : }
692 : : #endif
693 : :
694 : 13 : int pci_ext_cfg_avail(void)
695 : : {
696 [ + - ]: 13 : if (raw_pci_ext_ops)
697 : : return 1;
698 : : else
699 : 13 : return 0;
700 : : }
701 : :
702 : : #if IS_ENABLED(CONFIG_VMD)
703 : : struct pci_dev *pci_real_dma_dev(struct pci_dev *dev)
704 : : {
705 : : if (is_vmd(dev->bus))
706 : : return to_pci_sysdata(dev->bus)->vmd_dev;
707 : :
708 : : return dev;
709 : : }
710 : : #endif
|