]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/acpi/pci_root.c
PCI/ACPI: Support I/O resources when parsing host bridge resources
[mirror_ubuntu-artful-kernel.git] / drivers / acpi / pci_root.c
index ae3fe4e642035b2d51b2e3f6c4d93e68a6cb1bcc..d144168d4ef9dbfb66f45383ee62ab9bf00c0438 100644 (file)
@@ -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);