xref: /openbmc/linux/arch/x86/pci/common.c (revision fa6dae5d)
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