V4L/DVB (11387): Sensor orientation reporting
[safe/jmp/linux-2.6] / arch / x86 / pci / mmconfig_64.c
index 9207fd4..94349f8 100644 (file)
@@ -10,8 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <asm/e820.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
 
 /* Static virtual mapping of the MMCONFIG aperture */
 struct mmcfg_virt {
@@ -113,13 +112,18 @@ static struct pci_raw_ops pci_mmcfg = {
 static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
 {
        void __iomem *addr;
-       u32 size;
-
-       size = (cfg->end_bus_number + 1) << 20;
-       addr = ioremap_nocache(cfg->address, size);
+       u64 start, size;
+
+       start = cfg->start_bus_number;
+       start <<= 20;
+       start += cfg->address;
+       size = cfg->end_bus_number + 1 - cfg->start_bus_number;
+       size <<= 20;
+       addr = ioremap_nocache(start, size);
        if (addr) {
                printk(KERN_INFO "PCI: Using MMCONFIG at %Lx - %Lx\n",
-                      cfg->address, cfg->address + size - 1);
+                      start, start + size - 1);
+               addr -= cfg->start_bus_number << 20;
        }
        return addr;
 }
@@ -127,7 +131,7 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
 int __init pci_mmcfg_arch_init(void)
 {
        int i;
-       pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
+       pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) *
                                 pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {
                printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
@@ -141,9 +145,29 @@ int __init pci_mmcfg_arch_init(void)
                        printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
                                        "segment %d\n",
                                pci_mmcfg_config[i].pci_segment);
+                       pci_mmcfg_arch_free();
                        return 0;
                }
        }
        raw_pci_ext_ops = &pci_mmcfg;
        return 1;
 }
+
+void __init pci_mmcfg_arch_free(void)
+{
+       int i;
+
+       if (pci_mmcfg_virt == NULL)
+               return;
+
+       for (i = 0; i < pci_mmcfg_config_num; ++i) {
+               if (pci_mmcfg_virt[i].virt) {
+                       iounmap(pci_mmcfg_virt[i].virt + (pci_mmcfg_virt[i].cfg->start_bus_number << 20));
+                       pci_mmcfg_virt[i].virt = NULL;
+                       pci_mmcfg_virt[i].cfg = NULL;
+               }
+       }
+
+       kfree(pci_mmcfg_virt);
+       pci_mmcfg_virt = NULL;
+}