Commit 6e6f498b authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/resource' into next

* pci/resource:
  PCI: Simplify pci_create_attr() control flow
  PCI: Don't leak memory if sysfs_create_bin_file() fails
  PCI: Simplify sysfs ROM cleanup
  PCI: Remove unused IORESOURCE_ROM_COPY and IORESOURCE_ROM_BIOS_COPY
  MIPS: Loongson 3: Keep CPU physical (not virtual) addresses in shadow ROM resource
  MIPS: Loongson 3: Use temporary struct resource * to avoid repetition
  ia64/PCI: Keep CPU physical (not virtual) addresses in shadow ROM resource
  ia64/PCI: Use ioremap() instead of open-coded equivalent
  ia64/PCI: Use temporary struct resource * to avoid repetition
  PCI: Clean up pci_map_rom() whitespace
  PCI: Remove arch-specific IORESOURCE_ROM_SHADOW size from sysfs
  PCI: Set ROM shadow location in arch code, not in PCI core
  PCI: Don't enable/disable ROM BAR if we're using a RAM shadow copy
  PCI: Don't assign or reassign immutable resources
  PCI: Mark shadow copy of VGA ROM as IORESOURCE_PCI_FIXED
  x86/PCI: Mark Broadwell-EP Home Agent & PCU as having non-compliant BARs
  PCI: Disable IO/MEM decoding for devices with non-compliant BARs
parents cfeb8139 bd5174df
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
* *
* The standard boot ROM sequence for an x86 machine uses the BIOS * The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video * to select an initial video card for boot display. This boot video
* card will have it's BIOS copied to C0000 in system RAM. * card will have its BIOS copied to 0xC0000 in system RAM.
* IORESOURCE_ROM_SHADOW is used to associate the boot video * IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since * card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image. * the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. Before marking the device * See pci_map_rom() for use of this flag. Before marking the device
* with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
* by either arch cde or vga-arbitration, if so only apply the fixup to this * by either arch code or vga-arbitration; if so only apply the fixup to this
* already determined primary video card. * already-determined primary video card.
*/ */
static void pci_fixup_video(struct pci_dev *pdev) static void pci_fixup_video(struct pci_dev *pdev)
...@@ -32,6 +32,7 @@ static void pci_fixup_video(struct pci_dev *pdev) ...@@ -32,6 +32,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
struct pci_dev *bridge; struct pci_dev *bridge;
struct pci_bus *bus; struct pci_bus *bus;
u16 config; u16 config;
struct resource *res;
if ((strcmp(ia64_platform_name, "dig") != 0) if ((strcmp(ia64_platform_name, "dig") != 0)
&& (strcmp(ia64_platform_name, "hpzx1") != 0)) && (strcmp(ia64_platform_name, "hpzx1") != 0))
...@@ -61,8 +62,18 @@ static void pci_fixup_video(struct pci_dev *pdev) ...@@ -61,8 +62,18 @@ static void pci_fixup_video(struct pci_dev *pdev)
if (!vga_default_device() || pdev == vga_default_device()) { if (!vga_default_device() || pdev == vga_default_device()) {
pci_read_config_word(pdev, PCI_COMMAND, &config); pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; res = &pdev->resource[PCI_ROM_RESOURCE];
dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
pci_disable_rom(pdev);
if (res->parent)
release_resource(res);
res->start = 0xC0000;
res->end = res->start + 0x20000 - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
res);
} }
} }
} }
......
...@@ -429,7 +429,8 @@ sn_acpi_slot_fixup(struct pci_dev *dev) ...@@ -429,7 +429,8 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
void __iomem *addr; void __iomem *addr;
struct pcidev_info *pcidev_info = NULL; struct pcidev_info *pcidev_info = NULL;
struct sn_irq_info *sn_irq_info = NULL; struct sn_irq_info *sn_irq_info = NULL;
size_t image_size, size; struct resource *res;
size_t size;
if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
panic("%s: Failure obtaining pcidev_info for %s\n", panic("%s: Failure obtaining pcidev_info for %s\n",
...@@ -443,17 +444,20 @@ sn_acpi_slot_fixup(struct pci_dev *dev) ...@@ -443,17 +444,20 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
* of the shadowed copy, and the actual length of the ROM image. * of the shadowed copy, and the actual length of the ROM image.
*/ */
size = pci_resource_len(dev, PCI_ROM_RESOURCE); size = pci_resource_len(dev, PCI_ROM_RESOURCE);
addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
size); res = &dev->resource[PCI_ROM_RESOURCE];
image_size = pci_get_rom_size(dev, addr, size);
dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; pci_disable_rom(dev);
dev->resource[PCI_ROM_RESOURCE].end = if (res->parent)
(unsigned long) addr + image_size - 1; release_resource(res);
dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
res->start = pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE];
res->end = res->start + size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
} }
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
} }
EXPORT_SYMBOL(sn_acpi_slot_fixup); EXPORT_SYMBOL(sn_acpi_slot_fixup);
......
...@@ -150,7 +150,8 @@ void ...@@ -150,7 +150,8 @@ void
sn_io_slot_fixup(struct pci_dev *dev) sn_io_slot_fixup(struct pci_dev *dev)
{ {
int idx; int idx;
unsigned long addr, end, size, start; struct resource *res;
unsigned long addr, size;
struct pcidev_info *pcidev_info; struct pcidev_info *pcidev_info;
struct sn_irq_info *sn_irq_info; struct sn_irq_info *sn_irq_info;
int status; int status;
...@@ -175,55 +176,41 @@ sn_io_slot_fixup(struct pci_dev *dev) ...@@ -175,55 +176,41 @@ sn_io_slot_fixup(struct pci_dev *dev)
/* Copy over PIO Mapped Addresses */ /* Copy over PIO Mapped Addresses */
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
if (!pcidev_info->pdi_pio_mapped_addr[idx])
if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
continue; continue;
}
start = dev->resource[idx].start; res = &dev->resource[idx];
end = dev->resource[idx].end;
size = end - start; size = res->end - res->start;
if (size == 0) { if (size == 0)
continue; continue;
}
addr = pcidev_info->pdi_pio_mapped_addr[idx]; res->start = pcidev_info->pdi_pio_mapped_addr[idx];
addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; res->end = addr + size;
dev->resource[idx].start = addr;
dev->resource[idx].end = addr + size;
/* /*
* if it's already in the device structure, remove it before * if it's already in the device structure, remove it before
* inserting * inserting
*/ */
if (dev->resource[idx].parent && dev->resource[idx].parent->child) if (res->parent && res->parent->child)
release_resource(&dev->resource[idx]); release_resource(res);
if (dev->resource[idx].flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
insert_resource(&ioport_resource, &dev->resource[idx]); insert_resource(&ioport_resource, res);
else else
insert_resource(&iomem_resource, &dev->resource[idx]); insert_resource(&iomem_resource, res);
/* /*
* If ROM, set the actual ROM image size, and mark as * If ROM, mark as shadowed in PROM.
* shadowed in PROM.
*/ */
if (idx == PCI_ROM_RESOURCE) { if (idx == PCI_ROM_RESOURCE) {
size_t image_size; pci_disable_rom(dev);
void __iomem *rom; res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
size + 1);
image_size = pci_get_rom_size(dev, rom, size + 1);
dev->resource[PCI_ROM_RESOURCE].end =
dev->resource[PCI_ROM_RESOURCE].start +
image_size - 1;
dev->resource[PCI_ROM_RESOURCE].flags |=
IORESOURCE_ROM_BIOS_COPY;
} }
} }
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
} }
EXPORT_SYMBOL(sn_io_slot_fixup); EXPORT_SYMBOL(sn_io_slot_fixup);
/* /*
......
...@@ -40,20 +40,25 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ...@@ -40,20 +40,25 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static void pci_fixup_radeon(struct pci_dev *pdev) static void pci_fixup_radeon(struct pci_dev *pdev)
{ {
if (pdev->resource[PCI_ROM_RESOURCE].start) struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (res->start)
return; return;
if (!loongson_sysconf.vgabios_addr) if (!loongson_sysconf.vgabios_addr)
return; return;
pdev->resource[PCI_ROM_RESOURCE].start = pci_disable_rom(pdev);
loongson_sysconf.vgabios_addr; if (res->parent)
pdev->resource[PCI_ROM_RESOURCE].end = release_resource(res);
loongson_sysconf.vgabios_addr + 256*1024 - 1;
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY; res->start = virt_to_phys((void *) loongson_sysconf.vgabios_addr);
res->end = res->start + 256*1024 - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n", dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]); PCI_ROM_RESOURCE, res);
} }
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID, DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
......
...@@ -297,14 +297,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r ...@@ -297,14 +297,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
* *
* The standard boot ROM sequence for an x86 machine uses the BIOS * The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video * to select an initial video card for boot display. This boot video
* card will have it's BIOS copied to C0000 in system RAM. * card will have its BIOS copied to 0xC0000 in system RAM.
* IORESOURCE_ROM_SHADOW is used to associate the boot video * IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since * card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image. * the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. Before marking the device * See pci_map_rom() for use of this flag. Before marking the device
* with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
* by either arch cde or vga-arbitration, if so only apply the fixup to this * by either arch code or vga-arbitration; if so only apply the fixup to this
* already determined primary video card. * already-determined primary video card.
*/ */
static void pci_fixup_video(struct pci_dev *pdev) static void pci_fixup_video(struct pci_dev *pdev)
...@@ -312,6 +312,7 @@ static void pci_fixup_video(struct pci_dev *pdev) ...@@ -312,6 +312,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
struct pci_dev *bridge; struct pci_dev *bridge;
struct pci_bus *bus; struct pci_bus *bus;
u16 config; u16 config;
struct resource *res;
/* Is VGA routed to us? */ /* Is VGA routed to us? */
bus = pdev->bus; bus = pdev->bus;
...@@ -336,8 +337,18 @@ static void pci_fixup_video(struct pci_dev *pdev) ...@@ -336,8 +337,18 @@ static void pci_fixup_video(struct pci_dev *pdev)
if (!vga_default_device() || pdev == vga_default_device()) { if (!vga_default_device() || pdev == vga_default_device()) {
pci_read_config_word(pdev, PCI_COMMAND, &config); pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; res = &pdev->resource[PCI_ROM_RESOURCE];
dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
pci_disable_rom(pdev);
if (res->parent)
release_resource(res);
res->start = 0xC0000;
res->end = res->start + 0x20000 - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
IORESOURCE_PCI_FIXED;
dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
res);
} }
} }
} }
...@@ -540,3 +551,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev) ...@@ -540,3 +551,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev)
} }
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
static void pci_bdwep_bar(struct pci_dev *dev)
{
dev->non_compliant_bars = 1;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
...@@ -1138,33 +1138,36 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine) ...@@ -1138,33 +1138,36 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
/* allocate attribute structure, piggyback attribute name */ /* allocate attribute structure, piggyback attribute name */
int name_len = write_combine ? 13 : 10; int name_len = write_combine ? 13 : 10;
struct bin_attribute *res_attr; struct bin_attribute *res_attr;
char *res_attr_name;
int retval; int retval;
res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC); res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC);
if (res_attr) { if (!res_attr)
char *res_attr_name = (char *)(res_attr + 1); return -ENOMEM;
sysfs_bin_attr_init(res_attr); res_attr_name = (char *)(res_attr + 1);
if (write_combine) {
pdev->res_attr_wc[num] = res_attr; sysfs_bin_attr_init(res_attr);
sprintf(res_attr_name, "resource%d_wc", num); if (write_combine) {
res_attr->mmap = pci_mmap_resource_wc; pdev->res_attr_wc[num] = res_attr;
} else { sprintf(res_attr_name, "resource%d_wc", num);
pdev->res_attr[num] = res_attr; res_attr->mmap = pci_mmap_resource_wc;
sprintf(res_attr_name, "resource%d", num); } else {
res_attr->mmap = pci_mmap_resource_uc; pdev->res_attr[num] = res_attr;
} sprintf(res_attr_name, "resource%d", num);
if (pci_resource_flags(pdev, num) & IORESOURCE_IO) { res_attr->mmap = pci_mmap_resource_uc;
res_attr->read = pci_read_resource_io; }
res_attr->write = pci_write_resource_io; if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
} res_attr->read = pci_read_resource_io;
res_attr->attr.name = res_attr_name; res_attr->write = pci_write_resource_io;
res_attr->attr.mode = S_IRUSR | S_IWUSR; }
res_attr->size = pci_resource_len(pdev, num); res_attr->attr.name = res_attr_name;
res_attr->private = &pdev->resource[num]; res_attr->attr.mode = S_IRUSR | S_IWUSR;
retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr); res_attr->size = pci_resource_len(pdev, num);
} else res_attr->private = &pdev->resource[num];
retval = -ENOMEM; retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
if (retval)
kfree(res_attr);
return retval; return retval;
} }
...@@ -1360,7 +1363,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev) ...@@ -1360,7 +1363,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev) int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
{ {
int retval; int retval;
int rom_size = 0; int rom_size;
struct bin_attribute *attr; struct bin_attribute *attr;
if (!sysfs_initialized) if (!sysfs_initialized)
...@@ -1377,12 +1380,8 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev) ...@@ -1377,12 +1380,8 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
if (retval) if (retval)
goto err_config_file; goto err_config_file;
if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
rom_size = 0x20000;
/* If the device has a ROM, try to expose it in sysfs. */ /* If the device has a ROM, try to expose it in sysfs. */
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (rom_size) { if (rom_size) {
attr = kzalloc(sizeof(*attr), GFP_ATOMIC); attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
if (!attr) { if (!attr) {
...@@ -1413,7 +1412,7 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev) ...@@ -1413,7 +1412,7 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
return 0; return 0;
err_rom_file: err_rom_file:
if (rom_size) { if (pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
kfree(pdev->rom_attr); kfree(pdev->rom_attr);
pdev->rom_attr = NULL; pdev->rom_attr = NULL;
...@@ -1451,8 +1450,6 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev) ...@@ -1451,8 +1450,6 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
*/ */
void pci_remove_sysfs_dev_files(struct pci_dev *pdev) void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
{ {
int rom_size = 0;
if (!sysfs_initialized) if (!sysfs_initialized)
return; return;
...@@ -1465,18 +1462,13 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) ...@@ -1465,18 +1462,13 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
pci_remove_resource_files(pdev); pci_remove_resource_files(pdev);
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) if (pdev->rom_attr) {
rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
rom_size = 0x20000;
if (rom_size && pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
kfree(pdev->rom_attr); kfree(pdev->rom_attr);
pdev->rom_attr = NULL;
} }
pci_remove_firmware_label_files(pdev); pci_remove_firmware_label_files(pdev);
} }
static int __init pci_sysfs_init(void) static int __init pci_sysfs_init(void)
......
...@@ -179,6 +179,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, ...@@ -179,6 +179,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u16 orig_cmd; u16 orig_cmd;
struct pci_bus_region region, inverted_region; struct pci_bus_region region, inverted_region;
if (dev->non_compliant_bars)
return 0;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0; mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
/* No printks while decoding is disabled! */ /* No printks while decoding is disabled! */
...@@ -1191,6 +1194,7 @@ static void pci_msi_setup_pci_dev(struct pci_dev *dev) ...@@ -1191,6 +1194,7 @@ static void pci_msi_setup_pci_dev(struct pci_dev *dev)
int pci_setup_device(struct pci_dev *dev) int pci_setup_device(struct pci_dev *dev)
{ {
u32 class; u32 class;
u16 cmd;
u8 hdr_type; u8 hdr_type;
int pos = 0; int pos = 0;
struct pci_bus_region region; struct pci_bus_region region;
...@@ -1234,6 +1238,16 @@ int pci_setup_device(struct pci_dev *dev) ...@@ -1234,6 +1238,16 @@ int pci_setup_device(struct pci_dev *dev)
/* device class may be changed after fixup */ /* device class may be changed after fixup */
class = dev->class >> 8; class = dev->class >> 8;
if (dev->non_compliant_bars) {
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
dev_info(&dev->dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");
cmd &= ~PCI_COMMAND_IO;
cmd &= ~PCI_COMMAND_MEMORY;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
}
switch (dev->hdr_type) { /* header type */ switch (dev->hdr_type) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */ case PCI_HEADER_TYPE_NORMAL: /* standard header */
if (class == PCI_CLASS_BRIDGE_PCI) if (class == PCI_CLASS_BRIDGE_PCI)
......
...@@ -7,7 +7,6 @@ static void pci_free_resources(struct pci_dev *dev) ...@@ -7,7 +7,6 @@ static void pci_free_resources(struct pci_dev *dev)
{ {
int i; int i;
pci_cleanup_rom(dev);
for (i = 0; i < PCI_NUM_RESOURCES; i++) { for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *res = dev->resource + i; struct resource *res = dev->resource + i;
if (res->parent) if (res->parent)
......
...@@ -24,13 +24,17 @@ ...@@ -24,13 +24,17 @@
*/ */
int pci_enable_rom(struct pci_dev *pdev) int pci_enable_rom(struct pci_dev *pdev)
{ {
struct resource *res = pdev->resource + PCI_ROM_RESOURCE; struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
struct pci_bus_region region; struct pci_bus_region region;
u32 rom_addr; u32 rom_addr;
if (!res->flags) if (!res->flags)
return -1; return -1;
/* Nothing to enable if we're using a shadow copy in RAM */
if (res->flags & IORESOURCE_ROM_SHADOW)
return 0;
pcibios_resource_to_bus(pdev->bus, &region, res); pcibios_resource_to_bus(pdev->bus, &region, res);
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
rom_addr &= ~PCI_ROM_ADDRESS_MASK; rom_addr &= ~PCI_ROM_ADDRESS_MASK;
...@@ -49,7 +53,12 @@ EXPORT_SYMBOL_GPL(pci_enable_rom); ...@@ -49,7 +53,12 @@ EXPORT_SYMBOL_GPL(pci_enable_rom);
*/ */
void pci_disable_rom(struct pci_dev *pdev) void pci_disable_rom(struct pci_dev *pdev)
{ {
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
u32 rom_addr; u32 rom_addr;
if (res->flags & IORESOURCE_ROM_SHADOW)
return;
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
rom_addr &= ~PCI_ROM_ADDRESS_ENABLE; rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
...@@ -119,43 +128,23 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) ...@@ -119,43 +128,23 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
loff_t start; loff_t start;
void __iomem *rom; void __iomem *rom;
/* /* assign the ROM an address if it doesn't have one */
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
* memory map if the VGA enable bit of the Bridge Control register is return NULL;
* set for embedded VGA.
*/ start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
if (res->flags & IORESOURCE_ROM_SHADOW) { *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
/* primary video rom always starts here */ if (*size == 0)
start = (loff_t)0xC0000; return NULL;
*size = 0x20000; /* cover C000:0 through E000:0 */
} else { /* Enable ROM space decodes */
if (res->flags & if (pci_enable_rom(pdev))
(IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { return NULL;
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
return (void __iomem *)(unsigned long)
pci_resource_start(pdev, PCI_ROM_RESOURCE);
} else {
/* assign the ROM an address if it doesn't have one */
if (res->parent == NULL &&
pci_assign_resource(pdev, PCI_ROM_RESOURCE))
return NULL;
start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (*size == 0)
return NULL;
/* Enable ROM space decodes */
if (pci_enable_rom(pdev))
return NULL;
}
}
rom = ioremap(start, *size); rom = ioremap(start, *size);
if (!rom) { if (!rom) {
/* restore enable if ioremap fails */ /* restore enable if ioremap fails */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | if (!(res->flags & IORESOURCE_ROM_ENABLE))
IORESOURCE_ROM_SHADOW |
IORESOURCE_ROM_COPY)))
pci_disable_rom(pdev); pci_disable_rom(pdev);
return NULL; return NULL;
} }
...@@ -181,36 +170,14 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) ...@@ -181,36 +170,14 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
{ {
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return;
iounmap(rom); iounmap(rom);
/* Disable again before continuing, leave enabled if pci=rom */ /* Disable again before continuing */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW))) if (!(res->flags & IORESOURCE_ROM_ENABLE))
pci_disable_rom(pdev); pci_disable_rom(pdev);
} }
EXPORT_SYMBOL(pci_unmap_rom); EXPORT_SYMBOL(pci_unmap_rom);
/**
* pci_cleanup_rom - free the ROM copy created by pci_map_rom_copy
* @pdev: pointer to pci device struct
*
* Free the copied ROM if we allocated one.
*/
void pci_cleanup_rom(struct pci_dev *pdev)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (res->flags & IORESOURCE_ROM_COPY) {
kfree((void *)(unsigned long)res->start);
res->flags |= IORESOURCE_UNSET;
res->flags &= ~IORESOURCE_ROM_COPY;
res->start = 0;
res->end = 0;
}
}
/** /**
* pci_platform_rom - provides a pointer to any ROM image provided by the * pci_platform_rom - provides a pointer to any ROM image provided by the
* platform * platform
......
...@@ -276,6 +276,9 @@ int pci_assign_resource(struct pci_dev *dev, int resno) ...@@ -276,6 +276,9 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
resource_size_t align, size; resource_size_t align, size;
int ret; int ret;
if (res->flags & IORESOURCE_PCI_FIXED)
return 0;
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
align = pci_resource_alignment(dev, res); align = pci_resource_alignment(dev, res);
if (!align) { if (!align) {
...@@ -321,6 +324,9 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz ...@@ -321,6 +324,9 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
resource_size_t new_size; resource_size_t new_size;
int ret; int ret;
if (res->flags & IORESOURCE_PCI_FIXED)
return 0;
flags = res->flags; flags = res->flags;
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
if (!res->parent) { if (!res->parent) {
......
...@@ -98,9 +98,7 @@ struct resource { ...@@ -98,9 +98,7 @@ struct resource {
/* PCI ROM control bits (IORESOURCE_BITS) */ /* PCI ROM control bits (IORESOURCE_BITS) */
#define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ #define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
#define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ #define IORESOURCE_ROM_SHADOW (1<<1) /* Use RAM image, not ROM BAR */
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */
#define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */
/* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ /* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */
#define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ #define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */
......
...@@ -353,6 +353,7 @@ struct pci_dev { ...@@ -353,6 +353,7 @@ struct pci_dev {
unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */ unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */
unsigned int irq_managed:1; unsigned int irq_managed:1;
unsigned int has_secondary_link:1; unsigned int has_secondary_link:1;
unsigned int non_compliant_bars:1; /* broken BARs; ignore them */
pci_dev_flags_t dev_flags; pci_dev_flags_t dev_flags;
atomic_t enable_cnt; /* pci_enable_device has been called */ atomic_t enable_cnt; /* pci_enable_device has been called */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment