mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
PCI/ACPI: Support I/O resources when parsing host bridge resources
On platforms with memory-mapped I/O ports, such as ia64 and ARM64, we have to map the memory region and coordinate it with the arch's I/O port accessors. For ia64, we do this in arch code because it supports both dense (1 byte per I/O port) and sparse (1024 bytes per I/O port) memory mapping. For arm64, we only support dense mappings, which we can do in the generic code with pci_register_io_range() and pci_remap_iospace(). Add acpi_pci_root_remap_iospace() to remap dense memory-mapped I/O port space when adding a bridge, and call pci_unmap_iospace() to release the space when removing the bridge. [bhelgaas: changelog, move #ifdef inside acpi_pci_root_remap_iospace()] Signed-off-by: Jayachandran C <jchandra@broadcom.com> Signed-off-by: Sinan Kaya <okaya@codeaurora.org> [Tomasz: merged in Sinan's patch to unmap IO resources properly, updated changelog] Signed-off-by: Tomasz Nowicki <tn@semihalf.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
This commit is contained in:
parent
4d3f138459
commit
0a70abb380
@ -720,6 +720,36 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
|
||||
{
|
||||
#ifdef PCI_IOBASE
|
||||
struct resource *res = entry->res;
|
||||
resource_size_t cpu_addr = res->start;
|
||||
resource_size_t pci_addr = cpu_addr - entry->offset;
|
||||
resource_size_t length = resource_size(res);
|
||||
unsigned long port;
|
||||
|
||||
if (pci_register_io_range(cpu_addr, length))
|
||||
goto err;
|
||||
|
||||
port = pci_address_to_pio(cpu_addr);
|
||||
if (port == (unsigned long)-1)
|
||||
goto err;
|
||||
|
||||
res->start = port;
|
||||
res->end = port + length - 1;
|
||||
entry->offset = port - pci_addr;
|
||||
|
||||
if (pci_remap_iospace(res, cpu_addr) < 0)
|
||||
goto err;
|
||||
|
||||
pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
|
||||
return;
|
||||
err:
|
||||
res->flags |= IORESOURCE_DISABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
|
||||
{
|
||||
int ret;
|
||||
@ -740,6 +770,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
|
||||
"no IO and memory resources present in _CRS\n");
|
||||
else {
|
||||
resource_list_for_each_entry_safe(entry, tmp, list) {
|
||||
if (entry->res->flags & IORESOURCE_IO)
|
||||
acpi_pci_root_remap_iospace(entry);
|
||||
|
||||
if (entry->res->flags & IORESOURCE_DISABLED)
|
||||
resource_list_destroy_entry(entry);
|
||||
else
|
||||
@ -811,6 +844,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
|
||||
|
||||
resource_list_for_each_entry(entry, &bridge->windows) {
|
||||
res = entry->res;
|
||||
if (res->flags & IORESOURCE_IO)
|
||||
pci_unmap_iospace(res);
|
||||
if (res->parent &&
|
||||
(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
|
||||
release_resource(res);
|
||||
|
Loading…
Reference in New Issue
Block a user