aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2018-04-10 09:47:34 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-04-16 18:27:43 -0400
commitc2eead0503b1409bc6954b20585f2213b7e0552d (patch)
tree5329529cf10509374b01f2594304a22f6ef5755c
parent60cc43fc888428bb2f18f08997432d426a243338 (diff)
sparc/PCI: Request legacy VGA framebuffer only for VGA devices
Previously we unconditionally requested the legacy VGA framebuffer (bus address 0xa0000-0xbffff) before we even know what PCI devices are present, in these paths: pci_fire_pbm_init, schizo_pbm_init, pci_sun4v_pbm_init, psycho_pbm_init_common pci_determine_mem_io_space pci_register_legacy_regions p->start = mem_res->start + 0xa0000 request_resource(mem_res, p) # claim VGA framebuffer pci_scan_one_pbm pci_of_scan_bus # scan DT for PCI devices pci_claim_bus_resources # claim PCI device BARs If we found a PCI device with a BAR or bridge window that overlapped the framebuffer area, we complained about not being able to claim the BAR, e.g., pci 0000:00:01.0: can't claim BAR 8 [mem 0x1ff00000000-0x1ffbfffffff]: address conflict with Video RAM area [??? 0x1ff000a0000-0x1ff000bffff flags 0x80000000] pci 0000:02:01.0: can't claim BAR 8 [mem 0x1ff00100000-0x1ff028fffff]: no compatible bridge window pci 0000:03:0f.0: can't claim BAR 8 [mem 0x1ff00100000-0x1ff028fffff]: no compatible bridge window pci 0000:04:04.0: can't claim BAR 1 [mem 0x1ff02808000-0x1ff02808fff]: no compatible bridge window This may make the conflicting device unusable because we try not to enable devices that have unassigned or conflicting BARs, e.g., qla1280 0000:04:04.0: can't ioremap BAR 1: [mem size 0x00001000] qla1280: Unable to map I/O memory If there is no VGA device in the same PCI segment, there's no reason to reserve the framebuffer and there's no conflict. If there *is* a VGA device in the same segment, both the VGA device and the device with an overlapping BAR may respond to the framebuffer addresses, which may cause bus errors. Request the legacy framebuffer area only when we actually find a VGA device. The fact that VGA devices use the legacy framebuffer even though it's not reported in a BAR is not sparc-specific, so the reservation of that area could be made more generic in the PCI core eventually. Note that on some systems, e.g., Blade 100, we still report a conflict between an ISA bridge (00:07.0) and a VGA device (00:13.0): pci_bus 0000:00: root bus resource [mem 0x1ff00000000-0x1ffffffffff] (bus address [0x00000000-0xffffffff]) pci 0000:00:07.0: reg 0x14: [mem 0x1ff00000000-0x1ff000fffff] pci 0000:00:13.0: can't claim VGA legacy [mem 0x1ff000a0000-0x1ff000bffff]: address conflict with 0000:00:07.0 [mem 0x1ff00000000-0x1ff000fffff] This is probably harmless, but if the VGA device and something behind the ISA bridge both responded to reads of the framebuffer, it would cause a bus error. Link: https://lkml.kernel.org/r/alpine.LRH.2.21.1804112323170.25495@math.ut.ee Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=117191#c35 Reported-by: Meelis Roos <mroos@linux.ee> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--arch/sparc/kernel/pci.c42
-rw-r--r--arch/sparc/kernel/pci_common.c19
2 files changed, 42 insertions, 19 deletions
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 41b20edb427d..8a04983cf8a1 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -624,6 +624,45 @@ static void pci_bus_register_of_sysfs(struct pci_bus *bus)
624 pci_bus_register_of_sysfs(child_bus); 624 pci_bus_register_of_sysfs(child_bus);
625} 625}
626 626
627static void pci_claim_legacy_resources(struct pci_dev *dev)
628{
629 struct pci_bus_region region;
630 struct resource *p, *root, *conflict;
631
632 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
633 return;
634
635 p = kzalloc(sizeof(*p), GFP_KERNEL);
636 if (!p)
637 return;
638
639 p->name = "Video RAM area";
640 p->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
641
642 region.start = 0xa0000UL;
643 region.end = region.start + 0x1ffffUL;
644 pcibios_bus_to_resource(dev->bus, p, &region);
645
646 root = pci_find_parent_resource(dev, p);
647 if (!root) {
648 pci_info(dev, "can't claim VGA legacy %pR: no compatible bridge window\n", p);
649 goto err;
650 }
651
652 conflict = request_resource_conflict(root, p);
653 if (conflict) {
654 pci_info(dev, "can't claim VGA legacy %pR: address conflict with %s %pR\n",
655 p, conflict->name, conflict);
656 goto err;
657 }
658
659 pci_info(dev, "VGA legacy framebuffer %pR\n", p);
660 return;
661
662err:
663 kfree(p);
664}
665
627static void pci_claim_bus_resources(struct pci_bus *bus) 666static void pci_claim_bus_resources(struct pci_bus *bus)
628{ 667{
629 struct pci_bus *child_bus; 668 struct pci_bus *child_bus;
@@ -648,6 +687,8 @@ static void pci_claim_bus_resources(struct pci_bus *bus)
648 687
649 pci_claim_resource(dev, i); 688 pci_claim_resource(dev, i);
650 } 689 }
690
691 pci_claim_legacy_resources(dev);
651 } 692 }
652 693
653 list_for_each_entry(child_bus, &bus->children, node) 694 list_for_each_entry(child_bus, &bus->children, node)
@@ -687,6 +728,7 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
687 pci_bus_register_of_sysfs(bus); 728 pci_bus_register_of_sysfs(bus);
688 729
689 pci_claim_bus_resources(bus); 730 pci_claim_bus_resources(bus);
731
690 pci_bus_add_devices(bus); 732 pci_bus_add_devices(bus);
691 return bus; 733 return bus;
692} 734}
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c
index 38d46bcc8634..9bb6a192ef3f 100644
--- a/arch/sparc/kernel/pci_common.c
+++ b/arch/sparc/kernel/pci_common.c
@@ -329,23 +329,6 @@ void pci_get_pbm_props(struct pci_pbm_info *pbm)
329 } 329 }
330} 330}
331 331
332static void pci_register_legacy_regions(struct resource *io_res,
333 struct resource *mem_res)
334{
335 struct resource *p;
336
337 /* VGA Video RAM. */
338 p = kzalloc(sizeof(*p), GFP_KERNEL);
339 if (!p)
340 return;
341
342 p->name = "Video RAM area";
343 p->start = mem_res->start + 0xa0000UL;
344 p->end = p->start + 0x1ffffUL;
345 p->flags = IORESOURCE_BUSY;
346 request_resource(mem_res, p);
347}
348
349static void pci_register_iommu_region(struct pci_pbm_info *pbm) 332static void pci_register_iommu_region(struct pci_pbm_info *pbm)
350{ 333{
351 const u32 *vdma = of_get_property(pbm->op->dev.of_node, "virtual-dma", 334 const u32 *vdma = of_get_property(pbm->op->dev.of_node, "virtual-dma",
@@ -487,8 +470,6 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
487 if (pbm->mem64_space.flags) 470 if (pbm->mem64_space.flags)
488 request_resource(&iomem_resource, &pbm->mem64_space); 471 request_resource(&iomem_resource, &pbm->mem64_space);
489 472
490 pci_register_legacy_regions(&pbm->io_space,
491 &pbm->mem_space);
492 pci_register_iommu_region(pbm); 473 pci_register_iommu_region(pbm);
493} 474}
494 475