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
1 changed files with 35 additions and 0 deletions
|
@ -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 acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
|
||||||
{
|
{
|
||||||
int ret;
|
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");
|
"no IO and memory resources present in _CRS\n");
|
||||||
else {
|
else {
|
||||||
resource_list_for_each_entry_safe(entry, tmp, list) {
|
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)
|
if (entry->res->flags & IORESOURCE_DISABLED)
|
||||||
resource_list_destroy_entry(entry);
|
resource_list_destroy_entry(entry);
|
||||||
else
|
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) {
|
resource_list_for_each_entry(entry, &bridge->windows) {
|
||||||
res = entry->res;
|
res = entry->res;
|
||||||
|
if (res->flags & IORESOURCE_IO)
|
||||||
|
pci_unmap_iospace(res);
|
||||||
if (res->parent &&
|
if (res->parent &&
|
||||||
(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
|
(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
|
||||||
release_resource(res);
|
release_resource(res);
|
||||||
|
|
Loading…
Reference in a new issue