]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
PCI: Add support for non-BAR ROMs
authorMatthew Garrett <mjg@redhat.com>
Thu, 23 Aug 2012 16:36:42 +0000 (12:36 -0400)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 24 Aug 2012 15:29:14 +0000 (09:29 -0600)
Platforms may provide their own mechanisms for obtaining ROMs. Add support
for using data provided by the platform in that case.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/rom.c
include/linux/pci.h

index 48ebdb237f3f73d1e37e6e2022940ea5262d459c..46026e401b747cf4b28a1e61b461e4a02a945b71 100644 (file)
@@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        loff_t start;
        void __iomem *rom;
 
+       /*
+        * Some devices may provide ROMs via a source other than the BAR
+        */
+       if (pdev->rom && pdev->romlen) {
+               *size = pdev->romlen;
+               return phys_to_virt((phys_addr_t)pdev->rom);
        /*
         * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
         * memory map if the VGA enable bit of the Bridge Control register is
         * set for embedded VGA.
         */
-       if (res->flags & IORESOURCE_ROM_SHADOW) {
+       } else if (res->flags & IORESOURCE_ROM_SHADOW) {
                /* primary video rom always starts here */
                start = (loff_t)0xC0000;
                *size = 0x20000; /* cover C000:0 through E000:0 */
@@ -219,7 +225,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
        if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
                return;
 
-       iounmap(rom);
+       if (!pdev->rom || !pdev->romlen)
+               iounmap(rom);
 
        /* Disable again before continuing, leave enabled if pci=rom */
        if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
index 6a2625c63507f7d8517912b47f12778231edefd3..2668bb91c26408bf31ac1ba921d4a9c8da5c41be 100644 (file)
@@ -355,6 +355,8 @@ struct pci_dev {
        };
        struct pci_ats  *ats;   /* Address Translation Service */
 #endif
+       void *rom; /* Physical pointer to ROM if it's not from the BAR */
+       size_t romlen; /* Length of ROM if it's not from the BAR */
 };
 
 static inline struct pci_dev *pci_physfn(struct pci_dev *dev)