diff options
author | Matthew Garrett <mjg@redhat.com> | 2012-12-05 16:33:27 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-12-05 16:38:26 -0500 |
commit | 84c1b80e32638f881c17390dfe88143e5cd3f583 (patch) | |
tree | 64310c48ed0dce9d830bd60d280ac0fb59ee28a1 | |
parent | eca0d4676d8e29c209ddce0c0c1755472ffc70a6 (diff) |
PCI: Add support for non-BAR ROMs
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>
Tested-by: Seth Forshee <seth.forshee@canonical.com>
-rw-r--r-- | drivers/pci/rom.c | 11 | ||||
-rw-r--r-- | include/linux/pci.h | 2 |
2 files changed, 11 insertions, 2 deletions
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 0b3037ab8b93..3a3828fbc879 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -118,11 +118,17 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
118 | void __iomem *rom; | 118 | void __iomem *rom; |
119 | 119 | ||
120 | /* | 120 | /* |
121 | * Some devices may provide ROMs via a source other than the BAR | ||
122 | */ | ||
123 | if (pdev->rom && pdev->romlen) { | ||
124 | *size = pdev->romlen; | ||
125 | return phys_to_virt((phys_addr_t)pdev->rom); | ||
126 | /* | ||
121 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy | 127 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy |
122 | * memory map if the VGA enable bit of the Bridge Control register is | 128 | * memory map if the VGA enable bit of the Bridge Control register is |
123 | * set for embedded VGA. | 129 | * set for embedded VGA. |
124 | */ | 130 | */ |
125 | if (res->flags & IORESOURCE_ROM_SHADOW) { | 131 | } else if (res->flags & IORESOURCE_ROM_SHADOW) { |
126 | /* primary video rom always starts here */ | 132 | /* primary video rom always starts here */ |
127 | start = (loff_t)0xC0000; | 133 | start = (loff_t)0xC0000; |
128 | *size = 0x20000; /* cover C000:0 through E000:0 */ | 134 | *size = 0x20000; /* cover C000:0 through E000:0 */ |
@@ -181,7 +187,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) | |||
181 | if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) | 187 | if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) |
182 | return; | 188 | return; |
183 | 189 | ||
184 | iounmap(rom); | 190 | if (!pdev->rom || !pdev->romlen) |
191 | iounmap(rom); | ||
185 | 192 | ||
186 | /* Disable again before continuing, leave enabled if pci=rom */ | 193 | /* Disable again before continuing, leave enabled if pci=rom */ |
187 | if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) | 194 | if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 195c2593bd31..f116b2d859dc 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -333,6 +333,8 @@ struct pci_dev { | |||
333 | }; | 333 | }; |
334 | struct pci_ats *ats; /* Address Translation Service */ | 334 | struct pci_ats *ats; /* Address Translation Service */ |
335 | #endif | 335 | #endif |
336 | void *rom; /* Physical pointer to ROM if it's not from the BAR */ | ||
337 | size_t romlen; /* Length of ROM if it's not from the BAR */ | ||
336 | }; | 338 | }; |
337 | 339 | ||
338 | static inline struct pci_dev *pci_physfn(struct pci_dev *dev) | 340 | static inline struct pci_dev *pci_physfn(struct pci_dev *dev) |