1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2fb9aa6f1SThomas Gleixner /*
3fb9aa6f1SThomas Gleixner * Low-Level PCI Support for PC
4fb9aa6f1SThomas Gleixner *
5fb9aa6f1SThomas Gleixner * (c) 1999--2000 Martin Mares <mj@ucw.cz>
6fb9aa6f1SThomas Gleixner */
7fb9aa6f1SThomas Gleixner
8fb9aa6f1SThomas Gleixner #include <linux/sched.h>
9fb9aa6f1SThomas Gleixner #include <linux/pci.h>
1089016506SJiang Liu #include <linux/pci-acpi.h>
11fb9aa6f1SThomas Gleixner #include <linux/ioport.h>
12fb9aa6f1SThomas Gleixner #include <linux/init.h>
13fb9aa6f1SThomas Gleixner #include <linux/dmi.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
15fb9aa6f1SThomas Gleixner
16fb9aa6f1SThomas Gleixner #include <asm/acpi.h>
17fb9aa6f1SThomas Gleixner #include <asm/segment.h>
18fb9aa6f1SThomas Gleixner #include <asm/io.h>
19fb9aa6f1SThomas Gleixner #include <asm/smp.h>
2082487711SJaswinder Singh Rajput #include <asm/pci_x86.h>
21f9a37be0SMatthew Garrett #include <asm/setup.h>
222c681e6bSThomas Gleixner #include <asm/irqdomain.h>
23fb9aa6f1SThomas Gleixner
24fb9aa6f1SThomas Gleixner unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
25fb9aa6f1SThomas Gleixner PCI_PROBE_MMCONF;
26fb9aa6f1SThomas Gleixner
27fb9aa6f1SThomas Gleixner static int pci_bf_sort;
28fb9aa6f1SThomas Gleixner int pci_routeirq;
29a9322f64SStefan Assmann int noioapicquirk;
3041b9eb26SStefan Assmann #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
3141b9eb26SStefan Assmann int noioapicreroute = 0;
3241b9eb26SStefan Assmann #else
339197979bSStefan Assmann int noioapicreroute = 1;
3441b9eb26SStefan Assmann #endif
35fb9aa6f1SThomas Gleixner int pcibios_last_bus = -1;
36fb9aa6f1SThomas Gleixner unsigned long pirq_table_addr;
3772da0b07SJan Beulich const struct pci_raw_ops *__read_mostly raw_pci_ops;
3872da0b07SJan Beulich const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
39b6ce068aSMatthew Wilcox
raw_pci_read(unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 * val)40b6ce068aSMatthew Wilcox int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
41b6ce068aSMatthew Wilcox int reg, int len, u32 *val)
42b6ce068aSMatthew Wilcox {
43beef3129SMatthew Wilcox if (domain == 0 && reg < 256 && raw_pci_ops)
44b6ce068aSMatthew Wilcox return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
45b6ce068aSMatthew Wilcox if (raw_pci_ext_ops)
46b6ce068aSMatthew Wilcox return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
47b6ce068aSMatthew Wilcox return -EINVAL;
48b6ce068aSMatthew Wilcox }
49b6ce068aSMatthew Wilcox
raw_pci_write(unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 val)50b6ce068aSMatthew Wilcox int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
51b6ce068aSMatthew Wilcox int reg, int len, u32 val)
52b6ce068aSMatthew Wilcox {
53beef3129SMatthew Wilcox if (domain == 0 && reg < 256 && raw_pci_ops)
54b6ce068aSMatthew Wilcox return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
55b6ce068aSMatthew Wilcox if (raw_pci_ext_ops)
56b6ce068aSMatthew Wilcox return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
57b6ce068aSMatthew Wilcox return -EINVAL;
58b6ce068aSMatthew Wilcox }
59fb9aa6f1SThomas Gleixner
pci_read(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 * value)60fb9aa6f1SThomas Gleixner static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
61fb9aa6f1SThomas Gleixner {
62b6ce068aSMatthew Wilcox return raw_pci_read(pci_domain_nr(bus), bus->number,
63a79e4198SJeff Garzik devfn, where, size, value);
64fb9aa6f1SThomas Gleixner }
65fb9aa6f1SThomas Gleixner
pci_write(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 value)66fb9aa6f1SThomas Gleixner static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
67fb9aa6f1SThomas Gleixner {
68b6ce068aSMatthew Wilcox return raw_pci_write(pci_domain_nr(bus), bus->number,
69a79e4198SJeff Garzik devfn, where, size, value);
70fb9aa6f1SThomas Gleixner }
71fb9aa6f1SThomas Gleixner
72fb9aa6f1SThomas Gleixner struct pci_ops pci_root_ops = {
73fb9aa6f1SThomas Gleixner .read = pci_read,
74fb9aa6f1SThomas Gleixner .write = pci_write,
75fb9aa6f1SThomas Gleixner };
76fb9aa6f1SThomas Gleixner
77fb9aa6f1SThomas Gleixner /*
78df65c1bcSThomas Gleixner * This interrupt-safe spinlock protects all accesses to PCI configuration
79df65c1bcSThomas Gleixner * space, except for the mmconfig (ECAM) based operations.
80fb9aa6f1SThomas Gleixner */
81d19f61f0SThomas Gleixner DEFINE_RAW_SPINLOCK(pci_config_lock);
82fb9aa6f1SThomas Gleixner
can_skip_ioresource_align(const struct dmi_system_id * d)834ac9cbfaSMathias Krause static int __init can_skip_ioresource_align(const struct dmi_system_id *d)
8413a6ddb0SYinghai Lu {
8513a6ddb0SYinghai Lu pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
8613a6ddb0SYinghai Lu printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
8713a6ddb0SYinghai Lu return 0;
8813a6ddb0SYinghai Lu }
8913a6ddb0SYinghai Lu
904ac9cbfaSMathias Krause static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __initconst = {
9113a6ddb0SYinghai Lu /*
9213a6ddb0SYinghai Lu * Systems where PCI IO resource ISA alignment can be skipped
9313a6ddb0SYinghai Lu * when the ISA enable bit in the bridge control is not set
9413a6ddb0SYinghai Lu */
9513a6ddb0SYinghai Lu {
9613a6ddb0SYinghai Lu .callback = can_skip_ioresource_align,
9713a6ddb0SYinghai Lu .ident = "IBM System x3800",
9813a6ddb0SYinghai Lu .matches = {
9913a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
10013a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
10113a6ddb0SYinghai Lu },
10213a6ddb0SYinghai Lu },
10313a6ddb0SYinghai Lu {
10413a6ddb0SYinghai Lu .callback = can_skip_ioresource_align,
10513a6ddb0SYinghai Lu .ident = "IBM System x3850",
10613a6ddb0SYinghai Lu .matches = {
10713a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
10813a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
10913a6ddb0SYinghai Lu },
11013a6ddb0SYinghai Lu },
11113a6ddb0SYinghai Lu {
11213a6ddb0SYinghai Lu .callback = can_skip_ioresource_align,
11313a6ddb0SYinghai Lu .ident = "IBM System x3950",
11413a6ddb0SYinghai Lu .matches = {
11513a6ddb0SYinghai Lu DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
11613a6ddb0SYinghai Lu DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
11713a6ddb0SYinghai Lu },
11813a6ddb0SYinghai Lu },
11913a6ddb0SYinghai Lu {}
12013a6ddb0SYinghai Lu };
12113a6ddb0SYinghai Lu
dmi_check_skip_isa_align(void)12213a6ddb0SYinghai Lu void __init dmi_check_skip_isa_align(void)
12313a6ddb0SYinghai Lu {
12413a6ddb0SYinghai Lu dmi_check_system(can_skip_pciprobe_dmi_table);
12513a6ddb0SYinghai Lu }
12613a6ddb0SYinghai Lu
pcibios_fixup_device_resources(struct pci_dev * dev)127a18e3690SGreg Kroah-Hartman static void pcibios_fixup_device_resources(struct pci_dev *dev)
128bb71ad88SGary Hade {
129bb71ad88SGary Hade struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
1307bd1c365SMike Habeck struct resource *bar_r;
1317bd1c365SMike Habeck int bar;
1327bd1c365SMike Habeck
1337bd1c365SMike Habeck if (pci_probe & PCI_NOASSIGN_BARS) {
1347bd1c365SMike Habeck /*
1357bd1c365SMike Habeck * If the BIOS did not assign the BAR, zero out the
136386ed2abSAndrea Gelmini * resource so the kernel doesn't attempt to assign
1377bd1c365SMike Habeck * it later on in pci_assign_unassigned_resources
1387bd1c365SMike Habeck */
139c9c13ba4SDenis Efremov for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
1407bd1c365SMike Habeck bar_r = &dev->resource[bar];
1417bd1c365SMike Habeck if (bar_r->start == 0 && bar_r->end != 0) {
1427bd1c365SMike Habeck bar_r->flags = 0;
1437bd1c365SMike Habeck bar_r->end = 0;
1447bd1c365SMike Habeck }
1457bd1c365SMike Habeck }
1467bd1c365SMike Habeck }
147bb71ad88SGary Hade
148bb71ad88SGary Hade if (pci_probe & PCI_NOASSIGN_ROMS) {
149bb71ad88SGary Hade if (rom_r->parent)
150bb71ad88SGary Hade return;
151bb71ad88SGary Hade if (rom_r->start) {
152bb71ad88SGary Hade /* we deal with BIOS assigned ROM later */
153bb71ad88SGary Hade return;
154bb71ad88SGary Hade }
155bb71ad88SGary Hade rom_r->start = rom_r->end = rom_r->flags = 0;
156bb71ad88SGary Hade }
157bb71ad88SGary Hade }
158bb71ad88SGary Hade
159fb9aa6f1SThomas Gleixner /*
160fb9aa6f1SThomas Gleixner * Called after each bus is probed, but before its children
161fb9aa6f1SThomas Gleixner * are examined.
162fb9aa6f1SThomas Gleixner */
163fb9aa6f1SThomas Gleixner
pcibios_fixup_bus(struct pci_bus * b)164a18e3690SGreg Kroah-Hartman void pcibios_fixup_bus(struct pci_bus *b)
165fb9aa6f1SThomas Gleixner {
166bb71ad88SGary Hade struct pci_dev *dev;
167bb71ad88SGary Hade
168237865f1SBjorn Helgaas pci_read_bridge_bases(b);
169bb71ad88SGary Hade list_for_each_entry(dev, &b->devices, bus_list)
170bb71ad88SGary Hade pcibios_fixup_device_resources(dev);
171fb9aa6f1SThomas Gleixner }
172fb9aa6f1SThomas Gleixner
pcibios_add_bus(struct pci_bus * bus)17389016506SJiang Liu void pcibios_add_bus(struct pci_bus *bus)
17489016506SJiang Liu {
17589016506SJiang Liu acpi_pci_add_bus(bus);
17689016506SJiang Liu }
17789016506SJiang Liu
pcibios_remove_bus(struct pci_bus * bus)17889016506SJiang Liu void pcibios_remove_bus(struct pci_bus *bus)
17989016506SJiang Liu {
18089016506SJiang Liu acpi_pci_remove_bus(bus);
18189016506SJiang Liu }
18289016506SJiang Liu
183fb9aa6f1SThomas Gleixner /*
184fb9aa6f1SThomas Gleixner * Only use DMI information to set this if nothing was passed
185fb9aa6f1SThomas Gleixner * on the kernel command line (which was parsed earlier).
186fb9aa6f1SThomas Gleixner */
187fb9aa6f1SThomas Gleixner
set_bf_sort(const struct dmi_system_id * d)1884ac9cbfaSMathias Krause static int __init set_bf_sort(const struct dmi_system_id *d)
189fb9aa6f1SThomas Gleixner {
190fb9aa6f1SThomas Gleixner if (pci_bf_sort == pci_bf_sort_default) {
191fb9aa6f1SThomas Gleixner pci_bf_sort = pci_dmi_bf;
192fb9aa6f1SThomas Gleixner printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
193fb9aa6f1SThomas Gleixner }
194fb9aa6f1SThomas Gleixner return 0;
195fb9aa6f1SThomas Gleixner }
196fb9aa6f1SThomas Gleixner
read_dmi_type_b1(const struct dmi_header * dm,void * private_data)1974ac9cbfaSMathias Krause static void __init read_dmi_type_b1(const struct dmi_header *dm,
1986e8af08dSNarendra_K@Dell.com void *private_data)
1996e8af08dSNarendra_K@Dell.com {
200f5ab3b70SJean Delvare u8 *data = (u8 *)dm + 4;
2016e8af08dSNarendra_K@Dell.com
2026e8af08dSNarendra_K@Dell.com if (dm->type != 0xB1)
2036e8af08dSNarendra_K@Dell.com return;
204f5ab3b70SJean Delvare if ((((*(u32 *)data) >> 9) & 0x03) == 0x01)
205f5ab3b70SJean Delvare set_bf_sort((const struct dmi_system_id *)private_data);
2066e8af08dSNarendra_K@Dell.com }
2076e8af08dSNarendra_K@Dell.com
find_sort_method(const struct dmi_system_id * d)2084ac9cbfaSMathias Krause static int __init find_sort_method(const struct dmi_system_id *d)
2096e8af08dSNarendra_K@Dell.com {
210f5ab3b70SJean Delvare dmi_walk(read_dmi_type_b1, (void *)d);
2116e8af08dSNarendra_K@Dell.com return 0;
2126e8af08dSNarendra_K@Dell.com }
2136e8af08dSNarendra_K@Dell.com
214fb9aa6f1SThomas Gleixner /*
215fb9aa6f1SThomas Gleixner * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
216fb9aa6f1SThomas Gleixner */
217fb9aa6f1SThomas Gleixner #ifdef __i386__
assign_all_busses(const struct dmi_system_id * d)2184ac9cbfaSMathias Krause static int __init assign_all_busses(const struct dmi_system_id *d)
219fb9aa6f1SThomas Gleixner {
220fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ALL_BUSSES;
221fb9aa6f1SThomas Gleixner printk(KERN_INFO "%s detected: enabling PCI bus# renumbering"
222fb9aa6f1SThomas Gleixner " (pci=assign-busses)\n", d->ident);
223fb9aa6f1SThomas Gleixner return 0;
224fb9aa6f1SThomas Gleixner }
225fb9aa6f1SThomas Gleixner #endif
226fb9aa6f1SThomas Gleixner
set_scan_all(const struct dmi_system_id * d)2274ac9cbfaSMathias Krause static int __init set_scan_all(const struct dmi_system_id *d)
228284f5f9dSBjorn Helgaas {
229284f5f9dSBjorn Helgaas printk(KERN_INFO "PCI: %s detected, enabling pci=pcie_scan_all\n",
230284f5f9dSBjorn Helgaas d->ident);
231284f5f9dSBjorn Helgaas pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
232284f5f9dSBjorn Helgaas return 0;
233284f5f9dSBjorn Helgaas }
234284f5f9dSBjorn Helgaas
2354ac9cbfaSMathias Krause static const struct dmi_system_id pciprobe_dmi_table[] __initconst = {
236fb9aa6f1SThomas Gleixner #ifdef __i386__
237fb9aa6f1SThomas Gleixner /*
238fb9aa6f1SThomas Gleixner * Laptops which need pci=assign-busses to see Cardbus cards
239fb9aa6f1SThomas Gleixner */
240fb9aa6f1SThomas Gleixner {
241fb9aa6f1SThomas Gleixner .callback = assign_all_busses,
242fb9aa6f1SThomas Gleixner .ident = "Samsung X20 Laptop",
243fb9aa6f1SThomas Gleixner .matches = {
244fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
245fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"),
246fb9aa6f1SThomas Gleixner },
247fb9aa6f1SThomas Gleixner },
248fb9aa6f1SThomas Gleixner #endif /* __i386__ */
249fb9aa6f1SThomas Gleixner {
250fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
251fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 1950",
252fb9aa6f1SThomas Gleixner .matches = {
253fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
254fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
255fb9aa6f1SThomas Gleixner },
256fb9aa6f1SThomas Gleixner },
257fb9aa6f1SThomas Gleixner {
258fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
259fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 1955",
260fb9aa6f1SThomas Gleixner .matches = {
261fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
262fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
263fb9aa6f1SThomas Gleixner },
264fb9aa6f1SThomas Gleixner },
265fb9aa6f1SThomas Gleixner {
266fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
267fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 2900",
268fb9aa6f1SThomas Gleixner .matches = {
269fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
270fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
271fb9aa6f1SThomas Gleixner },
272fb9aa6f1SThomas Gleixner },
273fb9aa6f1SThomas Gleixner {
274fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
275fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge 2950",
276fb9aa6f1SThomas Gleixner .matches = {
277fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
278fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
279fb9aa6f1SThomas Gleixner },
280fb9aa6f1SThomas Gleixner },
281fb9aa6f1SThomas Gleixner {
282fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
283fb9aa6f1SThomas Gleixner .ident = "Dell PowerEdge R900",
284fb9aa6f1SThomas Gleixner .matches = {
285fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
286fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
287fb9aa6f1SThomas Gleixner },
288fb9aa6f1SThomas Gleixner },
289fb9aa6f1SThomas Gleixner {
2909b373ed1SNarendra_K@Dell.com .callback = find_sort_method,
2919b373ed1SNarendra_K@Dell.com .ident = "Dell System",
2929b373ed1SNarendra_K@Dell.com .matches = {
2939b373ed1SNarendra_K@Dell.com DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
2949b373ed1SNarendra_K@Dell.com },
2959b373ed1SNarendra_K@Dell.com },
2969b373ed1SNarendra_K@Dell.com {
297fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
298fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL20p G3",
299fb9aa6f1SThomas Gleixner .matches = {
300fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
301fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
302fb9aa6f1SThomas Gleixner },
303fb9aa6f1SThomas Gleixner },
304fb9aa6f1SThomas Gleixner {
305fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
306fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL20p G4",
307fb9aa6f1SThomas Gleixner .matches = {
308fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
309fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
310fb9aa6f1SThomas Gleixner },
311fb9aa6f1SThomas Gleixner },
312fb9aa6f1SThomas Gleixner {
313fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
314fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL30p G1",
315fb9aa6f1SThomas Gleixner .matches = {
316fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
317fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
318fb9aa6f1SThomas Gleixner },
319fb9aa6f1SThomas Gleixner },
320fb9aa6f1SThomas Gleixner {
321fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
322fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL25p G1",
323fb9aa6f1SThomas Gleixner .matches = {
324fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
325fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
326fb9aa6f1SThomas Gleixner },
327fb9aa6f1SThomas Gleixner },
328fb9aa6f1SThomas Gleixner {
329fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
330fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL35p G1",
331fb9aa6f1SThomas Gleixner .matches = {
332fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
333fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
334fb9aa6f1SThomas Gleixner },
335fb9aa6f1SThomas Gleixner },
336fb9aa6f1SThomas Gleixner {
337fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
338fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL45p G1",
339fb9aa6f1SThomas Gleixner .matches = {
340fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
341fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
342fb9aa6f1SThomas Gleixner },
343fb9aa6f1SThomas Gleixner },
344fb9aa6f1SThomas Gleixner {
345fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
346fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL45p G2",
347fb9aa6f1SThomas Gleixner .matches = {
348fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
349fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
350fb9aa6f1SThomas Gleixner },
351fb9aa6f1SThomas Gleixner },
352fb9aa6f1SThomas Gleixner {
353fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
354fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL460c G1",
355fb9aa6f1SThomas Gleixner .matches = {
356fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
357fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
358fb9aa6f1SThomas Gleixner },
359fb9aa6f1SThomas Gleixner },
360fb9aa6f1SThomas Gleixner {
361fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
362fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL465c G1",
363fb9aa6f1SThomas Gleixner .matches = {
364fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
365fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
366fb9aa6f1SThomas Gleixner },
367fb9aa6f1SThomas Gleixner },
368fb9aa6f1SThomas Gleixner {
369fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
370fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL480c G1",
371fb9aa6f1SThomas Gleixner .matches = {
372fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
373fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
374fb9aa6f1SThomas Gleixner },
375fb9aa6f1SThomas Gleixner },
376fb9aa6f1SThomas Gleixner {
377fb9aa6f1SThomas Gleixner .callback = set_bf_sort,
378fb9aa6f1SThomas Gleixner .ident = "HP ProLiant BL685c G1",
379fb9aa6f1SThomas Gleixner .matches = {
380fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_SYS_VENDOR, "HP"),
381fb9aa6f1SThomas Gleixner DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
382fb9aa6f1SThomas Gleixner },
383fb9aa6f1SThomas Gleixner },
3848f8ae1a7SMichal Schmidt {
3858f8ae1a7SMichal Schmidt .callback = set_bf_sort,
3868d64c781STony Camuso .ident = "HP ProLiant DL360",
3878f8ae1a7SMichal Schmidt .matches = {
3888f8ae1a7SMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"),
3898d64c781STony Camuso DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"),
3908f8ae1a7SMichal Schmidt },
3918f8ae1a7SMichal Schmidt },
3928f8ae1a7SMichal Schmidt {
3938f8ae1a7SMichal Schmidt .callback = set_bf_sort,
3948d64c781STony Camuso .ident = "HP ProLiant DL380",
3958f8ae1a7SMichal Schmidt .matches = {
3968f8ae1a7SMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"),
3978d64c781STony Camuso DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"),
3988f8ae1a7SMichal Schmidt },
3998f8ae1a7SMichal Schmidt },
4005b1ea82fSJuha Laiho #ifdef __i386__
4015b1ea82fSJuha Laiho {
4025b1ea82fSJuha Laiho .callback = assign_all_busses,
4035b1ea82fSJuha Laiho .ident = "Compaq EVO N800c",
4045b1ea82fSJuha Laiho .matches = {
4055b1ea82fSJuha Laiho DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
4065b1ea82fSJuha Laiho DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"),
4075b1ea82fSJuha Laiho },
4085b1ea82fSJuha Laiho },
4095b1ea82fSJuha Laiho #endif
410c82bc5adSMichal Schmidt {
411c82bc5adSMichal Schmidt .callback = set_bf_sort,
412739db07fSJesse Barnes .ident = "HP ProLiant DL385 G2",
413c82bc5adSMichal Schmidt .matches = {
414c82bc5adSMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"),
415739db07fSJesse Barnes DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"),
416c82bc5adSMichal Schmidt },
417c82bc5adSMichal Schmidt },
418c82bc5adSMichal Schmidt {
419c82bc5adSMichal Schmidt .callback = set_bf_sort,
420739db07fSJesse Barnes .ident = "HP ProLiant DL585 G2",
421c82bc5adSMichal Schmidt .matches = {
422c82bc5adSMichal Schmidt DMI_MATCH(DMI_SYS_VENDOR, "HP"),
423739db07fSJesse Barnes DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
424c82bc5adSMichal Schmidt },
425c82bc5adSMichal Schmidt },
426284f5f9dSBjorn Helgaas {
427284f5f9dSBjorn Helgaas .callback = set_scan_all,
428284f5f9dSBjorn Helgaas .ident = "Stratus/NEC ftServer",
429284f5f9dSBjorn Helgaas .matches = {
4301278998fSMyron Stowe DMI_MATCH(DMI_SYS_VENDOR, "Stratus"),
4311278998fSMyron Stowe DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"),
432284f5f9dSBjorn Helgaas },
433284f5f9dSBjorn Helgaas },
43451ac3d2fSCharlotte Richardson {
43551ac3d2fSCharlotte Richardson .callback = set_scan_all,
43651ac3d2fSCharlotte Richardson .ident = "Stratus/NEC ftServer",
43751ac3d2fSCharlotte Richardson .matches = {
43851ac3d2fSCharlotte Richardson DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
43951ac3d2fSCharlotte Richardson DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R32"),
44051ac3d2fSCharlotte Richardson },
44151ac3d2fSCharlotte Richardson },
44251ac3d2fSCharlotte Richardson {
44351ac3d2fSCharlotte Richardson .callback = set_scan_all,
44451ac3d2fSCharlotte Richardson .ident = "Stratus/NEC ftServer",
44551ac3d2fSCharlotte Richardson .matches = {
44651ac3d2fSCharlotte Richardson DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
44751ac3d2fSCharlotte Richardson DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R31"),
44851ac3d2fSCharlotte Richardson },
44951ac3d2fSCharlotte Richardson },
450fb9aa6f1SThomas Gleixner {}
451fb9aa6f1SThomas Gleixner };
452fb9aa6f1SThomas Gleixner
dmi_check_pciprobe(void)4530df18ff3SYinghai Lu void __init dmi_check_pciprobe(void)
4540df18ff3SYinghai Lu {
4550df18ff3SYinghai Lu dmi_check_system(pciprobe_dmi_table);
4560df18ff3SYinghai Lu }
4570df18ff3SYinghai Lu
pcibios_scan_root(int busnum)45849886cf4SBjorn Helgaas void pcibios_scan_root(int busnum)
459fb9aa6f1SThomas Gleixner {
460289a24a6SBjorn Helgaas struct pci_bus *bus;
461289a24a6SBjorn Helgaas struct pci_sysdata *sd;
462289a24a6SBjorn Helgaas LIST_HEAD(resources);
463289a24a6SBjorn Helgaas
464289a24a6SBjorn Helgaas sd = kzalloc(sizeof(*sd), GFP_KERNEL);
465289a24a6SBjorn Helgaas if (!sd) {
466289a24a6SBjorn Helgaas printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busnum);
46749886cf4SBjorn Helgaas return;
468289a24a6SBjorn Helgaas }
4696616dbdfSBjorn Helgaas sd->node = x86_pci_root_bus_node(busnum);
470289a24a6SBjorn Helgaas x86_pci_root_bus_resources(busnum, &resources);
471289a24a6SBjorn Helgaas printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
472289a24a6SBjorn Helgaas bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
473289a24a6SBjorn Helgaas if (!bus) {
474289a24a6SBjorn Helgaas pci_free_resource_list(&resources);
475289a24a6SBjorn Helgaas kfree(sd);
476b97ea289SYijing Wang return;
477289a24a6SBjorn Helgaas }
478b97ea289SYijing Wang pci_bus_add_devices(bus);
479fb9aa6f1SThomas Gleixner }
480fb9aa6f1SThomas Gleixner
pcibios_set_cache_line_size(void)48144de3395SAlex Nixon void __init pcibios_set_cache_line_size(void)
482fb9aa6f1SThomas Gleixner {
483fb9aa6f1SThomas Gleixner struct cpuinfo_x86 *c = &boot_cpu_data;
484fb9aa6f1SThomas Gleixner
485fb9aa6f1SThomas Gleixner /*
48676b1a87bSDave Jones * Set PCI cacheline size to that of the CPU if the CPU has reported it.
48776b1a87bSDave Jones * (For older CPUs that don't support cpuid, we se it to 32 bytes
48876b1a87bSDave Jones * It's also good for 386/486s (which actually have 16)
489fb9aa6f1SThomas Gleixner * as quite a few PCI devices do not support smaller values.
490fb9aa6f1SThomas Gleixner */
49176b1a87bSDave Jones if (c->x86_clflush_size > 0) {
49276b1a87bSDave Jones pci_dfl_cache_line_size = c->x86_clflush_size >> 2;
49376b1a87bSDave Jones printk(KERN_DEBUG "PCI: pci_cache_line_size set to %d bytes\n",
49476b1a87bSDave Jones pci_dfl_cache_line_size << 2);
49576b1a87bSDave Jones } else {
496ac1aa47bSJesse Barnes pci_dfl_cache_line_size = 32 >> 2;
49776b1a87bSDave Jones printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n");
49876b1a87bSDave Jones }
49944de3395SAlex Nixon }
500fb9aa6f1SThomas Gleixner
pcibios_init(void)50144de3395SAlex Nixon int __init pcibios_init(void)
50244de3395SAlex Nixon {
50335a6ae07SAdrian-Ken Rueegsegger if (!raw_pci_ops && !raw_pci_ext_ops) {
50444de3395SAlex Nixon printk(KERN_WARNING "PCI: System does not support PCI\n");
50544de3395SAlex Nixon return 0;
50644de3395SAlex Nixon }
50744de3395SAlex Nixon
50844de3395SAlex Nixon pcibios_set_cache_line_size();
509fb9aa6f1SThomas Gleixner pcibios_resource_survey();
510fb9aa6f1SThomas Gleixner
511fb9aa6f1SThomas Gleixner if (pci_bf_sort >= pci_force_bf)
512fb9aa6f1SThomas Gleixner pci_sort_breadthfirst();
513fb9aa6f1SThomas Gleixner return 0;
514fb9aa6f1SThomas Gleixner }
515fb9aa6f1SThomas Gleixner
pcibios_setup(char * str)51615fa325bSMyron Stowe char *__init pcibios_setup(char *str)
517fb9aa6f1SThomas Gleixner {
518fb9aa6f1SThomas Gleixner if (!strcmp(str, "off")) {
519fb9aa6f1SThomas Gleixner pci_probe = 0;
520fb9aa6f1SThomas Gleixner return NULL;
521fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "bfsort")) {
522fb9aa6f1SThomas Gleixner pci_bf_sort = pci_force_bf;
523fb9aa6f1SThomas Gleixner return NULL;
524fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "nobfsort")) {
525fb9aa6f1SThomas Gleixner pci_bf_sort = pci_force_nobf;
526fb9aa6f1SThomas Gleixner return NULL;
527fb9aa6f1SThomas Gleixner }
528fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_BIOS
529fb9aa6f1SThomas Gleixner else if (!strcmp(str, "bios")) {
530fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_BIOS;
531fb9aa6f1SThomas Gleixner return NULL;
532fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "nobios")) {
533fb9aa6f1SThomas Gleixner pci_probe &= ~PCI_PROBE_BIOS;
534fb9aa6f1SThomas Gleixner return NULL;
535fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "biosirq")) {
536fb9aa6f1SThomas Gleixner pci_probe |= PCI_BIOS_IRQ_SCAN;
537fb9aa6f1SThomas Gleixner return NULL;
538fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "pirqaddr=", 9)) {
539fb9aa6f1SThomas Gleixner pirq_table_addr = simple_strtoul(str+9, NULL, 0);
540fb9aa6f1SThomas Gleixner return NULL;
541fb9aa6f1SThomas Gleixner }
542fb9aa6f1SThomas Gleixner #endif
543fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_DIRECT
544fb9aa6f1SThomas Gleixner else if (!strcmp(str, "conf1")) {
545fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
546fb9aa6f1SThomas Gleixner return NULL;
547fb9aa6f1SThomas Gleixner }
548fb9aa6f1SThomas Gleixner else if (!strcmp(str, "conf2")) {
549fb9aa6f1SThomas Gleixner pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
550fb9aa6f1SThomas Gleixner return NULL;
551fb9aa6f1SThomas Gleixner }
552fb9aa6f1SThomas Gleixner #endif
553fb9aa6f1SThomas Gleixner #ifdef CONFIG_PCI_MMCONFIG
554fb9aa6f1SThomas Gleixner else if (!strcmp(str, "nommconf")) {
555fb9aa6f1SThomas Gleixner pci_probe &= ~PCI_PROBE_MMCONF;
556fb9aa6f1SThomas Gleixner return NULL;
557fb9aa6f1SThomas Gleixner }
5585f0b2976SYinghai Lu else if (!strcmp(str, "check_enable_amd_mmconf")) {
5595f0b2976SYinghai Lu pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
5605f0b2976SYinghai Lu return NULL;
5615f0b2976SYinghai Lu }
562fb9aa6f1SThomas Gleixner #endif
563fb9aa6f1SThomas Gleixner else if (!strcmp(str, "noacpi")) {
564fb9aa6f1SThomas Gleixner acpi_noirq_set();
565fb9aa6f1SThomas Gleixner return NULL;
566fb9aa6f1SThomas Gleixner }
567fb9aa6f1SThomas Gleixner else if (!strcmp(str, "noearly")) {
568fb9aa6f1SThomas Gleixner pci_probe |= PCI_PROBE_NOEARLY;
569fb9aa6f1SThomas Gleixner return NULL;
570fb9aa6f1SThomas Gleixner }
571fb9aa6f1SThomas Gleixner else if (!strcmp(str, "usepirqmask")) {
572fb9aa6f1SThomas Gleixner pci_probe |= PCI_USE_PIRQ_MASK;
573fb9aa6f1SThomas Gleixner return NULL;
574fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "irqmask=", 8)) {
575fb9aa6f1SThomas Gleixner pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
576fb9aa6f1SThomas Gleixner return NULL;
577fb9aa6f1SThomas Gleixner } else if (!strncmp(str, "lastbus=", 8)) {
578fb9aa6f1SThomas Gleixner pcibios_last_bus = simple_strtol(str+8, NULL, 0);
579fb9aa6f1SThomas Gleixner return NULL;
580c5f9ee3dSH. Peter Anvin } else if (!strcmp(str, "rom")) {
581fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ROMS;
582fb9aa6f1SThomas Gleixner return NULL;
583bb71ad88SGary Hade } else if (!strcmp(str, "norom")) {
584bb71ad88SGary Hade pci_probe |= PCI_NOASSIGN_ROMS;
585bb71ad88SGary Hade return NULL;
5867bd1c365SMike Habeck } else if (!strcmp(str, "nobar")) {
5877bd1c365SMike Habeck pci_probe |= PCI_NOASSIGN_BARS;
5887bd1c365SMike Habeck return NULL;
589fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "assign-busses")) {
590fb9aa6f1SThomas Gleixner pci_probe |= PCI_ASSIGN_ALL_BUSSES;
591fb9aa6f1SThomas Gleixner return NULL;
592236e946bSLinus Torvalds } else if (!strcmp(str, "use_crs")) {
593236e946bSLinus Torvalds pci_probe |= PCI_USE__CRS;
59462f420f8SGary Hade return NULL;
5957bc5e3f2SBjorn Helgaas } else if (!strcmp(str, "nocrs")) {
5967bc5e3f2SBjorn Helgaas pci_probe |= PCI_ROOT_NO_CRS;
5977bc5e3f2SBjorn Helgaas return NULL;
598*fa6dae5dSHans de Goede } else if (!strcmp(str, "use_e820")) {
599*fa6dae5dSHans de Goede pci_probe |= PCI_USE_E820;
600*fa6dae5dSHans de Goede add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
601*fa6dae5dSHans de Goede return NULL;
602*fa6dae5dSHans de Goede } else if (!strcmp(str, "no_e820")) {
603*fa6dae5dSHans de Goede pci_probe |= PCI_NO_E820;
604*fa6dae5dSHans de Goede add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
605*fa6dae5dSHans de Goede return NULL;
606f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= #ifdef CONFIG_PHYS_ADDR_T_64BIT
607f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= } else if (!strcmp(str, "big_root_window")) {
608f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= pci_probe |= PCI_BIG_ROOT_WINDOW;
609f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= return NULL;
610f32ab754S=?UTF-8?q?Christian=20K=C3=B6nig?= #endif
611fb9aa6f1SThomas Gleixner } else if (!strcmp(str, "routeirq")) {
612fb9aa6f1SThomas Gleixner pci_routeirq = 1;
613fb9aa6f1SThomas Gleixner return NULL;
61413a6ddb0SYinghai Lu } else if (!strcmp(str, "skip_isa_align")) {
61513a6ddb0SYinghai Lu pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
61613a6ddb0SYinghai Lu return NULL;
617a9322f64SStefan Assmann } else if (!strcmp(str, "noioapicquirk")) {
618a9322f64SStefan Assmann noioapicquirk = 1;
619a9322f64SStefan Assmann return NULL;
6209197979bSStefan Assmann } else if (!strcmp(str, "ioapicreroute")) {
6219197979bSStefan Assmann if (noioapicreroute != -1)
6229197979bSStefan Assmann noioapicreroute = 0;
6239197979bSStefan Assmann return NULL;
62441b9eb26SStefan Assmann } else if (!strcmp(str, "noioapicreroute")) {
62541b9eb26SStefan Assmann if (noioapicreroute != -1)
62641b9eb26SStefan Assmann noioapicreroute = 1;
62741b9eb26SStefan Assmann return NULL;
628fb9aa6f1SThomas Gleixner }
629fb9aa6f1SThomas Gleixner return str;
630fb9aa6f1SThomas Gleixner }
631fb9aa6f1SThomas Gleixner
pcibios_assign_all_busses(void)632fb9aa6f1SThomas Gleixner unsigned int pcibios_assign_all_busses(void)
633fb9aa6f1SThomas Gleixner {
634fb9aa6f1SThomas Gleixner return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
635fb9aa6f1SThomas Gleixner }
636fb9aa6f1SThomas Gleixner
set_dev_domain_options(struct pci_dev * pdev)6373161832dSKeith Busch static void set_dev_domain_options(struct pci_dev *pdev)
6383161832dSKeith Busch {
6393161832dSKeith Busch if (is_vmd(pdev->bus))
6403161832dSKeith Busch pdev->hotplug_user_indicators = 1;
6413161832dSKeith Busch }
6423161832dSKeith Busch
pcibios_device_add(struct pci_dev * dev)64306dc660eSOliver O'Halloran int pcibios_device_add(struct pci_dev *dev)
644f9a37be0SMatthew Garrett {
645f9a37be0SMatthew Garrett struct pci_setup_rom *rom;
6462c681e6bSThomas Gleixner struct irq_domain *msidom;
6472c681e6bSThomas Gleixner struct setup_data *data;
648f9a37be0SMatthew Garrett u64 pa_data;
649f9a37be0SMatthew Garrett
650f9a37be0SMatthew Garrett pa_data = boot_params.hdr.setup_data;
651f9a37be0SMatthew Garrett while (pa_data) {
652f7750a79STom Lendacky data = memremap(pa_data, sizeof(*rom), MEMREMAP_WB);
65365694c5aSMatt Fleming if (!data)
65465694c5aSMatt Fleming return -ENOMEM;
655f9a37be0SMatthew Garrett
656f9a37be0SMatthew Garrett if (data->type == SETUP_PCI) {
657f9a37be0SMatthew Garrett rom = (struct pci_setup_rom *)data;
658f9a37be0SMatthew Garrett
659f9a37be0SMatthew Garrett if ((pci_domain_nr(dev->bus) == rom->segment) &&
660f9a37be0SMatthew Garrett (dev->bus->number == rom->bus) &&
661f9a37be0SMatthew Garrett (PCI_SLOT(dev->devfn) == rom->device) &&
662f9a37be0SMatthew Garrett (PCI_FUNC(dev->devfn) == rom->function) &&
663f9a37be0SMatthew Garrett (dev->vendor == rom->vendor) &&
664f9a37be0SMatthew Garrett (dev->device == rom->devid)) {
665dbd3fc33SBjorn Helgaas dev->rom = pa_data +
666dbd3fc33SBjorn Helgaas offsetof(struct pci_setup_rom, romdata);
667f9a37be0SMatthew Garrett dev->romlen = rom->pcilen;
668f9a37be0SMatthew Garrett }
669f9a37be0SMatthew Garrett }
670f9a37be0SMatthew Garrett pa_data = data->next;
671f7750a79STom Lendacky memunmap(data);
672f9a37be0SMatthew Garrett }
6733161832dSKeith Busch set_dev_domain_options(dev);
6742c681e6bSThomas Gleixner
6752c681e6bSThomas Gleixner /*
6762c681e6bSThomas Gleixner * Setup the initial MSI domain of the device. If the underlying
6772c681e6bSThomas Gleixner * bus has a PCI/MSI irqdomain associated use the bus domain,
6782c681e6bSThomas Gleixner * otherwise set the default domain. This ensures that special irq
6792c681e6bSThomas Gleixner * domains e.g. VMD are preserved. The default ensures initial
6802c681e6bSThomas Gleixner * operation if irq remapping is not active. If irq remapping is
6812c681e6bSThomas Gleixner * active it will overwrite the domain pointer when the device is
6822c681e6bSThomas Gleixner * associated to a remapping domain.
6832c681e6bSThomas Gleixner */
6842c681e6bSThomas Gleixner msidom = dev_get_msi_domain(&dev->bus->dev);
6852c681e6bSThomas Gleixner if (!msidom)
6862c681e6bSThomas Gleixner msidom = x86_pci_msi_default_domain;
6872c681e6bSThomas Gleixner dev_set_msi_domain(&dev->dev, msidom);
688f9a37be0SMatthew Garrett return 0;
689f9a37be0SMatthew Garrett }
690f9a37be0SMatthew Garrett
pcibios_enable_device(struct pci_dev * dev,int mask)691991de2e5SJiang Liu int pcibios_enable_device(struct pci_dev *dev, int mask)
692991de2e5SJiang Liu {
6936c777e87SBjorn Helgaas int err;
6946c777e87SBjorn Helgaas
6956c777e87SBjorn Helgaas if ((err = pci_enable_resources(dev, mask)) < 0)
6966c777e87SBjorn Helgaas return err;
6976c777e87SBjorn Helgaas
6986c777e87SBjorn Helgaas if (!pci_dev_msi_enabled(dev))
6996c777e87SBjorn Helgaas return pcibios_enable_irq(dev);
7006c777e87SBjorn Helgaas return 0;
7016c777e87SBjorn Helgaas }
7026c777e87SBjorn Helgaas
pcibios_disable_device(struct pci_dev * dev)7036c777e87SBjorn Helgaas void pcibios_disable_device (struct pci_dev *dev)
7046c777e87SBjorn Helgaas {
7056c777e87SBjorn Helgaas if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
7066c777e87SBjorn Helgaas pcibios_disable_irq(dev);
707991de2e5SJiang Liu }
708991de2e5SJiang Liu
709153654dbSRui Wang #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
pcibios_release_device(struct pci_dev * dev)710153654dbSRui Wang void pcibios_release_device(struct pci_dev *dev)
711153654dbSRui Wang {
712153654dbSRui Wang if (atomic_dec_return(&dev->enable_cnt) >= 0)
713153654dbSRui Wang pcibios_disable_device(dev);
714153654dbSRui Wang
715153654dbSRui Wang }
716153654dbSRui Wang #endif
717153654dbSRui Wang
pci_ext_cfg_avail(void)718642c92daSTaku Izumi int pci_ext_cfg_avail(void)
7190ef5f8f6SAndrew Patterson {
7200ef5f8f6SAndrew Patterson if (raw_pci_ext_ops)
7210ef5f8f6SAndrew Patterson return 1;
7220ef5f8f6SAndrew Patterson else
7230ef5f8f6SAndrew Patterson return 0;
7240ef5f8f6SAndrew Patterson }
7252856ba60SJon Derrick
7262856ba60SJon Derrick #if IS_ENABLED(CONFIG_VMD)
pci_real_dma_dev(struct pci_dev * dev)7272856ba60SJon Derrick struct pci_dev *pci_real_dma_dev(struct pci_dev *dev)
7282856ba60SJon Derrick {
7292856ba60SJon Derrick if (is_vmd(dev->bus))
7302856ba60SJon Derrick return to_pci_sysdata(dev->bus)->vmd_dev;
7312856ba60SJon Derrick
7322856ba60SJon Derrick return dev;
7332856ba60SJon Derrick }
7342856ba60SJon Derrick #endif
735