Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a70abb3 authored by Jayachandran C's avatar Jayachandran C Committed by Bjorn Helgaas
Browse files

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: default avatarJayachandran C <jchandra@broadcom.com>
Signed-off-by: default avatarSinan Kaya <okaya@codeaurora.org>
[Tomasz: merged in Sinan's patch to unmap IO resources properly, updated changelog]
Signed-off-by: default avatarTomasz Nowicki <tn@semihalf.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
parent 4d3f1384
Loading
Loading
Loading
Loading
+35 −0
Original line number Original line Diff line number Diff line
@@ -720,6 +720,36 @@ static void acpi_pci_root_validate_resources(struct device *dev,
	}
	}
}
}


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);