From 63e22924f5dc08badf9870c4a52ef4e7f7cbf218 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 1 Mar 2016 11:32:29 -0600 Subject: PCI: Mark shadow copy of VGA ROM as IORESOURCE_PCI_FIXED A shadow copy of an option ROM is placed by the BIOS as a fixed address. Set IORESOURCE_PCI_FIXED to indicate that we can't move the shadow copy. This prevents warnings like the following when we assign resources: BAR 6: [??? 0x00000000 flags 0x2] has bogus alignment This warning is emitted by pdev_sort_resources(), which already ignores IORESOURCE_PCI_FIXED resources. Link: http://lkml.kernel.org/r/CA+55aFyVMfTBB0oz_yx8+eQOEJnzGtCsYSj9QuhEpdZ9BHdq5A@mail.gmail.com Signed-off-by: Bjorn Helgaas --- arch/ia64/pci/fixup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/ia64') diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c index fc505d58f078..fd9ceff2b5a5 100644 --- a/arch/ia64/pci/fixup.c +++ b/arch/ia64/pci/fixup.c @@ -61,7 +61,8 @@ static void pci_fixup_video(struct pci_dev *pdev) if (!vga_default_device() || pdev == vga_default_device()) { pci_read_config_word(pdev, PCI_COMMAND, &config); if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW | + IORESOURCE_PCI_FIXED; dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n"); } } -- cgit v1.2.3 From 0c0e0736acad4e76e718456c75d78ad95eea0011 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 1 Mar 2016 11:38:46 -0600 Subject: PCI: Set ROM shadow location in arch code, not in PCI core IORESOURCE_ROM_SHADOW means there is a copy of a device's option ROM in RAM. The existence of such a copy and its location are arch-specific. Previously the IORESOURCE_ROM_SHADOW flag was set in arch code, but the 0xC0000-0xDFFFF location was hard-coded into the PCI core. If we're using a shadow copy in RAM, disable the ROM BAR and release the address space it was consuming. Move the location information from the PCI core to the arch code that sets IORESOURCE_ROM_SHADOW. Save the location of the RAM copy in the struct resource for PCI_ROM_RESOURCE. After this change, pci_map_rom() will call pci_assign_resource() and pci_enable_rom() for these IORESOURCE_ROM_SHADOW resources, which we did not do before. This is safe because: - pci_assign_resource() will do nothing because the resource is marked IORESOURCE_PCI_FIXED, which means we can't move it, and - pci_enable_rom() will not turn on the ROM BAR's enable bit because the resource is marked IORESOURCE_ROM_SHADOW, which means it is in RAM rather than in PCI memory space. Storing the location in the struct resource means "lspci" will show the shadow location, not the value from the ROM BAR. Signed-off-by: Bjorn Helgaas --- arch/ia64/pci/fixup.c | 22 ++++++++++++++++------ arch/x86/pci/fixup.c | 22 ++++++++++++++++------ drivers/pci/rom.c | 11 ----------- include/linux/ioport.h | 2 +- 4 files changed, 33 insertions(+), 24 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c index fd9ceff2b5a5..41caa99add51 100644 --- a/arch/ia64/pci/fixup.c +++ b/arch/ia64/pci/fixup.c @@ -17,14 +17,14 @@ * * The standard boot ROM sequence for an x86 machine uses the BIOS * 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 * card with this copy. On laptops this copy has to be used since * the main ROM may be compressed or combined with another image. * 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 - * by either arch cde or vga-arbitration, if so only apply the fixup to this - * already determined primary video card. + * by either arch code or vga-arbitration; if so only apply the fixup to this + * already-determined primary video card. */ 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_bus *bus; u16 config; + struct resource *res; if ((strcmp(ia64_platform_name, "dig") != 0) && (strcmp(ia64_platform_name, "hpzx1") != 0)) @@ -61,9 +62,18 @@ static void pci_fixup_video(struct pci_dev *pdev) if (!vga_default_device() || pdev == vga_default_device()) { pci_read_config_word(pdev, PCI_COMMAND, &config); if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW | - IORESOURCE_PCI_FIXED; - dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n"); + res = &pdev->resource[PCI_ROM_RESOURCE]; + + 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); } } } diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index dac027c1adb1..b7de1929714b 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -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 * 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 * card with this copy. On laptops this copy has to be used since * the main ROM may be compressed or combined with another image. * 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 - * by either arch cde or vga-arbitration, if so only apply the fixup to this - * already determined primary video card. + * by either arch code or vga-arbitration; if so only apply the fixup to this + * already-determined primary video card. */ 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_bus *bus; u16 config; + struct resource *res; /* Is VGA routed to us? */ bus = pdev->bus; @@ -336,9 +337,18 @@ static void pci_fixup_video(struct pci_dev *pdev) if (!vga_default_device() || pdev == vga_default_device()) { pci_read_config_word(pdev, PCI_COMMAND, &config); if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW | - IORESOURCE_PCI_FIXED; - dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n"); + res = &pdev->resource[PCI_ROM_RESOURCE]; + + 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); } } } diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 5da8d061d600..80e82b13292f 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -128,16 +128,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) loff_t start; void __iomem *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) { - /* primary video rom always starts here */ - start = (loff_t)0xC0000; - *size = 0x20000; /* cover C000:0 through E000:0 */ - } else { if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); @@ -157,7 +147,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) if (pci_enable_rom(pdev)) return NULL; } - } rom = ioremap(start, *size); if (!rom) { diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 24bea087e7af..2cf16673f17a 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -98,7 +98,7 @@ struct resource { /* PCI ROM control bits (IORESOURCE_BITS) */ #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 */ -- cgit v1.2.3 From ab97b8cc560eabfd8139dd97924a09e46a3c9632 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 2 Mar 2016 16:16:03 -0600 Subject: ia64/PCI: Use temporary struct resource * to avoid repetition Use a temporary struct resource pointer to avoid needless repetition of "dev->resource[idx]". No functional change intended. Signed-off-by: Bjorn Helgaas --- arch/ia64/sn/kernel/io_acpi_init.c | 10 +++++----- arch/ia64/sn/kernel/io_init.c | 39 +++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 27 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index 0640739cc20c..815c29163e1d 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -429,6 +429,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev) void __iomem *addr; struct pcidev_info *pcidev_info = NULL; struct sn_irq_info *sn_irq_info = NULL; + struct resource *res; size_t image_size, size; if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { @@ -446,14 +447,13 @@ sn_acpi_slot_fixup(struct pci_dev *dev) addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], size); image_size = pci_get_rom_size(dev, addr, size); - dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; - dev->resource[PCI_ROM_RESOURCE].end = - (unsigned long) addr + image_size - 1; - dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; + res = &dev->resource[PCI_ROM_RESOURCE]; + res->start = (unsigned long) addr; + res->end = (unsigned long) addr + image_size - 1; + res->flags |= IORESOURCE_ROM_BIOS_COPY; } sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); } - EXPORT_SYMBOL(sn_acpi_slot_fixup); diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 1be65eb074ec..40c02635f19f 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -150,7 +150,8 @@ void sn_io_slot_fixup(struct pci_dev *dev) { int idx; - unsigned long addr, end, size, start; + struct resource *res; + unsigned long addr, size; struct pcidev_info *pcidev_info; struct sn_irq_info *sn_irq_info; int status; @@ -175,33 +176,31 @@ sn_io_slot_fixup(struct pci_dev *dev) /* Copy over PIO Mapped Addresses */ 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; - } - start = dev->resource[idx].start; - end = dev->resource[idx].end; - size = end - start; - if (size == 0) { + res = &dev->resource[idx]; + + size = res->end - res->start; + if (size == 0) continue; - } + addr = pcidev_info->pdi_pio_mapped_addr[idx]; addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; - dev->resource[idx].start = addr; - dev->resource[idx].end = addr + size; + res->start = addr; + res->end = addr + size; /* * if it's already in the device structure, remove it before * inserting */ - if (dev->resource[idx].parent && dev->resource[idx].parent->child) - release_resource(&dev->resource[idx]); + if (res->parent && res->parent->child) + release_resource(res); - if (dev->resource[idx].flags & IORESOURCE_IO) - insert_resource(&ioport_resource, &dev->resource[idx]); + if (res->flags & IORESOURCE_IO) + insert_resource(&ioport_resource, res); else - insert_resource(&iomem_resource, &dev->resource[idx]); + insert_resource(&iomem_resource, res); /* * If ROM, set the actual ROM image size, and mark as * shadowed in PROM. @@ -213,17 +212,13 @@ sn_io_slot_fixup(struct pci_dev *dev) 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; + res->end = res->start + image_size - 1; + res->flags |= IORESOURCE_ROM_BIOS_COPY; } } sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info); } - EXPORT_SYMBOL(sn_io_slot_fixup); /* -- cgit v1.2.3 From f976721e826e06ba1cdfce701495b49e2e25289d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 2 Mar 2016 16:20:18 -0600 Subject: ia64/PCI: Use ioremap() instead of open-coded equivalent Depositing __IA64_UNCACHED_OFFSET in the upper address bits is essentially equivalent to ioremap(): it converts a CPU physical address to a virtual address using the ia64 uncacheable identity map. Call ioremap() instead of doing the phys-to-virt conversion manually with __IA64_UNCACHED_OFFSET. Note that this makes it obvious that (a) we're putting a virtual address in a struct resource, and (b) we're passing a virtual address to ioremap() below in the PCI_ROM_RESOURCE case. These are both pre-existing problems that I'll resolve next. Signed-off-by: Bjorn Helgaas --- arch/ia64/sn/kernel/io_init.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 40c02635f19f..0227e202b6bb 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -185,9 +185,8 @@ sn_io_slot_fixup(struct pci_dev *dev) if (size == 0) continue; - addr = pcidev_info->pdi_pio_mapped_addr[idx]; - addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET; - res->start = addr; + res->start = ioremap(pcidev_info->pdi_pio_mapped_addr[idx], + size + 1); res->end = addr + size; /* -- cgit v1.2.3 From 240504adaf0798a5ab18fac46ae782d3b004859f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 2 Mar 2016 16:06:32 -0600 Subject: ia64/PCI: Keep CPU physical (not virtual) addresses in shadow ROM resource A struct resource contains CPU physical addresses, not virtual addresses. But sn_acpi_slot_fixup() and sn_io_slot_fixup() stored the virtual address of a shadow ROM copy in the resource. To compensate, pci_map_rom() had a special case that returned the resource address directly rather than calling ioremap() on it. When we're using a shadow copy in RAM or PROM, disable the ROM BAR and release the address space it was consuming. Store the CPU physical (not virtual) address in the shadow ROM resource, and mark the resource as IORESOURCE_ROM_SHADOW so we use the normal pci_map_rom() path that ioremaps the copy. Signed-off-by: Bjorn Helgaas --- arch/ia64/sn/kernel/io_acpi_init.c | 18 +++++++++++------- arch/ia64/sn/kernel/io_init.c | 17 +++++------------ 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'arch/ia64') diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index 815c29163e1d..231234c8d113 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -430,7 +430,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev) struct pcidev_info *pcidev_info = NULL; struct sn_irq_info *sn_irq_info = NULL; struct resource *res; - size_t image_size, size; + size_t size; if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) { panic("%s: Failure obtaining pcidev_info for %s\n", @@ -444,13 +444,17 @@ sn_acpi_slot_fixup(struct pci_dev *dev) * of the shadowed copy, and the actual length of the ROM image. */ size = pci_resource_len(dev, PCI_ROM_RESOURCE); - addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], - size); - image_size = pci_get_rom_size(dev, addr, size); + res = &dev->resource[PCI_ROM_RESOURCE]; - res->start = (unsigned long) addr; - res->end = (unsigned long) addr + image_size - 1; - res->flags |= IORESOURCE_ROM_BIOS_COPY; + + pci_disable_rom(dev); + if (res->parent) + release_resource(res); + + 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); } diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 0227e202b6bb..c15a41e2d1f2 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -185,8 +185,7 @@ sn_io_slot_fixup(struct pci_dev *dev) if (size == 0) continue; - res->start = ioremap(pcidev_info->pdi_pio_mapped_addr[idx], - size + 1); + res->start = pcidev_info->pdi_pio_mapped_addr[idx]; res->end = addr + size; /* @@ -201,18 +200,12 @@ sn_io_slot_fixup(struct pci_dev *dev) else insert_resource(&iomem_resource, res); /* - * If ROM, set the actual ROM image size, and mark as - * shadowed in PROM. + * If ROM, mark as shadowed in PROM. */ if (idx == PCI_ROM_RESOURCE) { - size_t image_size; - void __iomem *rom; - - rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE), - size + 1); - image_size = pci_get_rom_size(dev, rom, size + 1); - res->end = res->start + image_size - 1; - res->flags |= IORESOURCE_ROM_BIOS_COPY; + pci_disable_rom(dev); + res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW | + IORESOURCE_PCI_FIXED; } } -- cgit v1.2.3