162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Low-Level PCI Access for i386 machines 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 1993, 1994 Drew Eckhardt 662306a36Sopenharmony_ci * Visionary Computing 762306a36Sopenharmony_ci * (Unix and Linux consulting and custom programming) 862306a36Sopenharmony_ci * Drew@Colorado.EDU 962306a36Sopenharmony_ci * +1 (303) 786-7975 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Drew's work was sponsored by: 1262306a36Sopenharmony_ci * iX Multiuser Multitasking Magazine 1362306a36Sopenharmony_ci * Hannover, Germany 1462306a36Sopenharmony_ci * hm@ix.de 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Copyright 1997--2000 Martin Mares <mj@ucw.cz> 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * For more information, please consult the following manuals (look at 1962306a36Sopenharmony_ci * http://www.pcisig.com/ for how to get them): 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * PCI BIOS Specification 2262306a36Sopenharmony_ci * PCI Local Bus Specification 2362306a36Sopenharmony_ci * PCI to PCI Bridge Specification 2462306a36Sopenharmony_ci * PCI System Design Guide 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <linux/types.h> 2962306a36Sopenharmony_ci#include <linux/kernel.h> 3062306a36Sopenharmony_ci#include <linux/export.h> 3162306a36Sopenharmony_ci#include <linux/pci.h> 3262306a36Sopenharmony_ci#include <linux/init.h> 3362306a36Sopenharmony_ci#include <linux/ioport.h> 3462306a36Sopenharmony_ci#include <linux/errno.h> 3562306a36Sopenharmony_ci#include <linux/memblock.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <asm/memtype.h> 3862306a36Sopenharmony_ci#include <asm/e820/api.h> 3962306a36Sopenharmony_ci#include <asm/pci_x86.h> 4062306a36Sopenharmony_ci#include <asm/io_apic.h> 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * This list of dynamic mappings is for temporarily maintaining 4562306a36Sopenharmony_ci * original BIOS BAR addresses for possible reinstatement. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_cistruct pcibios_fwaddrmap { 4862306a36Sopenharmony_ci struct list_head list; 4962306a36Sopenharmony_ci struct pci_dev *dev; 5062306a36Sopenharmony_ci resource_size_t fw_addr[DEVICE_COUNT_RESOURCE]; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic LIST_HEAD(pcibios_fwaddrmappings); 5462306a36Sopenharmony_cistatic DEFINE_SPINLOCK(pcibios_fwaddrmap_lock); 5562306a36Sopenharmony_cistatic bool pcibios_fw_addr_done; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* Must be called with 'pcibios_fwaddrmap_lock' lock held. */ 5862306a36Sopenharmony_cistatic struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct pcibios_fwaddrmap *map; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci lockdep_assert_held(&pcibios_fwaddrmap_lock); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci list_for_each_entry(map, &pcibios_fwaddrmappings, list) 6562306a36Sopenharmony_ci if (map->dev == dev) 6662306a36Sopenharmony_ci return map; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return NULL; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic void 7262306a36Sopenharmony_cipcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci unsigned long flags; 7562306a36Sopenharmony_ci struct pcibios_fwaddrmap *map; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (pcibios_fw_addr_done) 7862306a36Sopenharmony_ci return; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); 8162306a36Sopenharmony_ci map = pcibios_fwaddrmap_lookup(dev); 8262306a36Sopenharmony_ci if (!map) { 8362306a36Sopenharmony_ci spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); 8462306a36Sopenharmony_ci map = kzalloc(sizeof(*map), GFP_KERNEL); 8562306a36Sopenharmony_ci if (!map) 8662306a36Sopenharmony_ci return; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci map->dev = pci_dev_get(dev); 8962306a36Sopenharmony_ci map->fw_addr[idx] = fw_addr; 9062306a36Sopenharmony_ci INIT_LIST_HEAD(&map->list); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); 9362306a36Sopenharmony_ci list_add_tail(&map->list, &pcibios_fwaddrmappings); 9462306a36Sopenharmony_ci } else 9562306a36Sopenharmony_ci map->fw_addr[idx] = fw_addr; 9662306a36Sopenharmony_ci spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciresource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci unsigned long flags; 10262306a36Sopenharmony_ci struct pcibios_fwaddrmap *map; 10362306a36Sopenharmony_ci resource_size_t fw_addr = 0; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (pcibios_fw_addr_done) 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); 10962306a36Sopenharmony_ci map = pcibios_fwaddrmap_lookup(dev); 11062306a36Sopenharmony_ci if (map) 11162306a36Sopenharmony_ci fw_addr = map->fw_addr[idx]; 11262306a36Sopenharmony_ci spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci return fw_addr; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic void __init pcibios_fw_addr_list_del(void) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci unsigned long flags; 12062306a36Sopenharmony_ci struct pcibios_fwaddrmap *entry, *next; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); 12362306a36Sopenharmony_ci list_for_each_entry_safe(entry, next, &pcibios_fwaddrmappings, list) { 12462306a36Sopenharmony_ci list_del(&entry->list); 12562306a36Sopenharmony_ci pci_dev_put(entry->dev); 12662306a36Sopenharmony_ci kfree(entry); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); 12962306a36Sopenharmony_ci pcibios_fw_addr_done = true; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int 13362306a36Sopenharmony_ciskip_isa_ioresource_align(struct pci_dev *dev) { 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) && 13662306a36Sopenharmony_ci !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA)) 13762306a36Sopenharmony_ci return 1; 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * We need to avoid collisions with `mirrored' VGA ports 14362306a36Sopenharmony_ci * and other strange ISA hardware, so we always want the 14462306a36Sopenharmony_ci * addresses to be allocated in the 0x000-0x0ff region 14562306a36Sopenharmony_ci * modulo 0x400. 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * Why? Because some silly external IO cards only decode 14862306a36Sopenharmony_ci * the low 10 bits of the IO address. The 0x00-0xff region 14962306a36Sopenharmony_ci * is reserved for motherboard devices that decode all 16 15062306a36Sopenharmony_ci * bits, so it's ok to allocate at, say, 0x2800-0x28ff, 15162306a36Sopenharmony_ci * but we want to try to avoid allocating at 0x2900-0x2bff 15262306a36Sopenharmony_ci * which might have be mirrored at 0x0100-0x03ff.. 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_ciresource_size_t 15562306a36Sopenharmony_cipcibios_align_resource(void *data, const struct resource *res, 15662306a36Sopenharmony_ci resource_size_t size, resource_size_t align) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct pci_dev *dev = data; 15962306a36Sopenharmony_ci resource_size_t start = res->start; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (res->flags & IORESOURCE_IO) { 16262306a36Sopenharmony_ci if (skip_isa_ioresource_align(dev)) 16362306a36Sopenharmony_ci return start; 16462306a36Sopenharmony_ci if (start & 0x300) 16562306a36Sopenharmony_ci start = (start + 0x3ff) & ~0x3ff; 16662306a36Sopenharmony_ci } else if (res->flags & IORESOURCE_MEM) { 16762306a36Sopenharmony_ci /* The low 1MB range is reserved for ISA cards */ 16862306a36Sopenharmony_ci if (start < BIOS_END) 16962306a36Sopenharmony_ci start = BIOS_END; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci return start; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ciEXPORT_SYMBOL(pcibios_align_resource); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* 17662306a36Sopenharmony_ci * Handle resources of PCI devices. If the world were perfect, we could 17762306a36Sopenharmony_ci * just allocate all the resource regions and do nothing more. It isn't. 17862306a36Sopenharmony_ci * On the other hand, we cannot just re-allocate all devices, as it would 17962306a36Sopenharmony_ci * require us to know lots of host bridge internals. So we attempt to 18062306a36Sopenharmony_ci * keep as much of the original configuration as possible, but tweak it 18162306a36Sopenharmony_ci * when it's found to be wrong. 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * Known BIOS problems we have to work around: 18462306a36Sopenharmony_ci * - I/O or memory regions not configured 18562306a36Sopenharmony_ci * - regions configured, but not enabled in the command register 18662306a36Sopenharmony_ci * - bogus I/O addresses above 64K used 18762306a36Sopenharmony_ci * - expansion ROMs left enabled (this may sound harmless, but given 18862306a36Sopenharmony_ci * the fact the PCI specs explicitly allow address decoders to be 18962306a36Sopenharmony_ci * shared between expansion ROMs and other resource regions, it's 19062306a36Sopenharmony_ci * at least dangerous) 19162306a36Sopenharmony_ci * - bad resource sizes or overlaps with other regions 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * Our solution: 19462306a36Sopenharmony_ci * (1) Allocate resources for all buses behind PCI-to-PCI bridges. 19562306a36Sopenharmony_ci * This gives us fixed barriers on where we can allocate. 19662306a36Sopenharmony_ci * (2) Allocate resources for all enabled devices. If there is 19762306a36Sopenharmony_ci * a collision, just mark the resource as unallocated. Also 19862306a36Sopenharmony_ci * disable expansion ROMs during this step. 19962306a36Sopenharmony_ci * (3) Try to allocate resources for disabled devices. If the 20062306a36Sopenharmony_ci * resources were assigned correctly, everything goes well, 20162306a36Sopenharmony_ci * if they weren't, they won't disturb allocation of other 20262306a36Sopenharmony_ci * resources. 20362306a36Sopenharmony_ci * (4) Assign new addresses to resources which were either 20462306a36Sopenharmony_ci * not configured at all or misconfigured. If explicitly 20562306a36Sopenharmony_ci * requested by the user, configure expansion ROM address 20662306a36Sopenharmony_ci * as well. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic void pcibios_allocate_bridge_resources(struct pci_dev *dev) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci int idx; 21262306a36Sopenharmony_ci struct resource *r; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { 21562306a36Sopenharmony_ci r = &dev->resource[idx]; 21662306a36Sopenharmony_ci if (!r->flags) 21762306a36Sopenharmony_ci continue; 21862306a36Sopenharmony_ci if (r->parent) /* Already allocated */ 21962306a36Sopenharmony_ci continue; 22062306a36Sopenharmony_ci if (!r->start || pci_claim_bridge_resource(dev, idx) < 0) { 22162306a36Sopenharmony_ci /* 22262306a36Sopenharmony_ci * Something is wrong with the region. 22362306a36Sopenharmony_ci * Invalidate the resource to prevent 22462306a36Sopenharmony_ci * child resource allocations in this 22562306a36Sopenharmony_ci * range. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci r->start = r->end = 0; 22862306a36Sopenharmony_ci r->flags = 0; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic void pcibios_allocate_bus_resources(struct pci_bus *bus) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct pci_bus *child; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* Depth-First Search on bus tree */ 23862306a36Sopenharmony_ci if (bus->self) 23962306a36Sopenharmony_ci pcibios_allocate_bridge_resources(bus->self); 24062306a36Sopenharmony_ci list_for_each_entry(child, &bus->children, node) 24162306a36Sopenharmony_ci pcibios_allocate_bus_resources(child); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistruct pci_check_idx_range { 24562306a36Sopenharmony_ci int start; 24662306a36Sopenharmony_ci int end; 24762306a36Sopenharmony_ci}; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci int idx, disabled, i; 25262306a36Sopenharmony_ci u16 command; 25362306a36Sopenharmony_ci struct resource *r; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci struct pci_check_idx_range idx_range[] = { 25662306a36Sopenharmony_ci { PCI_STD_RESOURCES, PCI_STD_RESOURCE_END }, 25762306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 25862306a36Sopenharmony_ci { PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END }, 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci }; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &command); 26362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(idx_range); i++) 26462306a36Sopenharmony_ci for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) { 26562306a36Sopenharmony_ci r = &dev->resource[idx]; 26662306a36Sopenharmony_ci if (r->parent) /* Already allocated */ 26762306a36Sopenharmony_ci continue; 26862306a36Sopenharmony_ci if (!r->start) /* Address not assigned at all */ 26962306a36Sopenharmony_ci continue; 27062306a36Sopenharmony_ci if (r->flags & IORESOURCE_IO) 27162306a36Sopenharmony_ci disabled = !(command & PCI_COMMAND_IO); 27262306a36Sopenharmony_ci else 27362306a36Sopenharmony_ci disabled = !(command & PCI_COMMAND_MEMORY); 27462306a36Sopenharmony_ci if (pass == disabled) { 27562306a36Sopenharmony_ci dev_dbg(&dev->dev, 27662306a36Sopenharmony_ci "BAR %d: reserving %pr (d=%d, p=%d)\n", 27762306a36Sopenharmony_ci idx, r, disabled, pass); 27862306a36Sopenharmony_ci if (pci_claim_resource(dev, idx) < 0) { 27962306a36Sopenharmony_ci if (r->flags & IORESOURCE_PCI_FIXED) { 28062306a36Sopenharmony_ci dev_info(&dev->dev, "BAR %d %pR is immovable\n", 28162306a36Sopenharmony_ci idx, r); 28262306a36Sopenharmony_ci } else { 28362306a36Sopenharmony_ci /* We'll assign a new address later */ 28462306a36Sopenharmony_ci pcibios_save_fw_addr(dev, 28562306a36Sopenharmony_ci idx, r->start); 28662306a36Sopenharmony_ci r->end -= r->start; 28762306a36Sopenharmony_ci r->start = 0; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci if (!pass) { 29362306a36Sopenharmony_ci r = &dev->resource[PCI_ROM_RESOURCE]; 29462306a36Sopenharmony_ci if (r->flags & IORESOURCE_ROM_ENABLE) { 29562306a36Sopenharmony_ci /* Turn the ROM off, leave the resource region, 29662306a36Sopenharmony_ci * but keep it unregistered. */ 29762306a36Sopenharmony_ci u32 reg; 29862306a36Sopenharmony_ci dev_dbg(&dev->dev, "disabling ROM %pR\n", r); 29962306a36Sopenharmony_ci r->flags &= ~IORESOURCE_ROM_ENABLE; 30062306a36Sopenharmony_ci pci_read_config_dword(dev, dev->rom_base_reg, ®); 30162306a36Sopenharmony_ci pci_write_config_dword(dev, dev->rom_base_reg, 30262306a36Sopenharmony_ci reg & ~PCI_ROM_ADDRESS_ENABLE); 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic void pcibios_allocate_resources(struct pci_bus *bus, int pass) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct pci_dev *dev; 31062306a36Sopenharmony_ci struct pci_bus *child; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 31362306a36Sopenharmony_ci pcibios_allocate_dev_resources(dev, pass); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci child = dev->subordinate; 31662306a36Sopenharmony_ci if (child) 31762306a36Sopenharmony_ci pcibios_allocate_resources(child, pass); 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic void pcibios_allocate_dev_rom_resource(struct pci_dev *dev) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct resource *r; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* 32662306a36Sopenharmony_ci * Try to use BIOS settings for ROMs, otherwise let 32762306a36Sopenharmony_ci * pci_assign_unassigned_resources() allocate the new 32862306a36Sopenharmony_ci * addresses. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci r = &dev->resource[PCI_ROM_RESOURCE]; 33162306a36Sopenharmony_ci if (!r->flags || !r->start) 33262306a36Sopenharmony_ci return; 33362306a36Sopenharmony_ci if (r->parent) /* Already allocated */ 33462306a36Sopenharmony_ci return; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { 33762306a36Sopenharmony_ci r->end -= r->start; 33862306a36Sopenharmony_ci r->start = 0; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_cistatic void pcibios_allocate_rom_resources(struct pci_bus *bus) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci struct pci_dev *dev; 34462306a36Sopenharmony_ci struct pci_bus *child; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 34762306a36Sopenharmony_ci pcibios_allocate_dev_rom_resource(dev); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci child = dev->subordinate; 35062306a36Sopenharmony_ci if (child) 35162306a36Sopenharmony_ci pcibios_allocate_rom_resources(child); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic int __init pcibios_assign_resources(void) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct pci_bus *bus; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if (!(pci_probe & PCI_ASSIGN_ROMS)) 36062306a36Sopenharmony_ci list_for_each_entry(bus, &pci_root_buses, node) 36162306a36Sopenharmony_ci pcibios_allocate_rom_resources(bus); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci pci_assign_unassigned_resources(); 36462306a36Sopenharmony_ci pcibios_fw_addr_list_del(); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return 0; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/* 37062306a36Sopenharmony_ci * This is an fs_initcall (one below subsys_initcall) in order to reserve 37162306a36Sopenharmony_ci * resources properly. 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_cifs_initcall(pcibios_assign_resources); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_civoid pcibios_resource_survey_bus(struct pci_bus *bus) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n"); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci pcibios_allocate_bus_resources(bus); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci pcibios_allocate_resources(bus, 0); 38262306a36Sopenharmony_ci pcibios_allocate_resources(bus, 1); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if (!(pci_probe & PCI_ASSIGN_ROMS)) 38562306a36Sopenharmony_ci pcibios_allocate_rom_resources(bus); 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_civoid __init pcibios_resource_survey(void) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct pci_bus *bus; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci DBG("PCI: Allocating resources\n"); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci list_for_each_entry(bus, &pci_root_buses, node) 39562306a36Sopenharmony_ci pcibios_allocate_bus_resources(bus); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci list_for_each_entry(bus, &pci_root_buses, node) 39862306a36Sopenharmony_ci pcibios_allocate_resources(bus, 0); 39962306a36Sopenharmony_ci list_for_each_entry(bus, &pci_root_buses, node) 40062306a36Sopenharmony_ci pcibios_allocate_resources(bus, 1); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci e820__reserve_resources_late(); 40362306a36Sopenharmony_ci /* 40462306a36Sopenharmony_ci * Insert the IO APIC resources after PCI initialization has 40562306a36Sopenharmony_ci * occurred to handle IO APICS that are mapped in on a BAR in 40662306a36Sopenharmony_ci * PCI space, but before trying to assign unassigned pci res. 40762306a36Sopenharmony_ci */ 40862306a36Sopenharmony_ci ioapic_insert_resources(); 40962306a36Sopenharmony_ci} 410