ing the generic pcibios_resource_to_bus(). Implement an architecture specific pcibios_resource_to_bus() function to correctly translate PCI BAR resource addresses to bus addresses for s390. Similarly add architecture specific pcibios_bus_to_resource function to do the reverse translation. Reviewed-by: Niklas Schnelle Signed-off-by: Farhan Ali --- arch/s390/pci/pci.c | 74 +++++++++++++++++++++++++++++++++++++++ drivers/pci/host-bridge.c | 4 +-- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index c82c577db2bc..cacad02b2b7f 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -264,6 +264,80 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, return 0; } +void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, + struct resource *res) +{ + struct zpci_bus *zbus = bus->sysdata; + struct zpci_bar_struct *zbar; + struct zpci_dev *zdev; + + region->start = res->start; + region->end = res->end; + + for (int i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) { + int j = 0; + + zbar = NULL; + zdev = zbus->function[i]; + if (!zdev) + continue; + + for (j = 0; j < PCI_STD_NUM_BARS; j++) { + if (zdev->bars[j].res->start == res->start && + zdev->bars[j].res->end == res->end && + res->flags & IORESOURCE_MEM) { + zbar = &zdev->bars[j]; + break; + } + } + + if (zbar) { + /* only MMIO is supported */ + region->start = zbar->val & PCI_BASE_ADDRESS_MEM_MASK; + if (zbar->val & PCI_BASE_ADDRESS_MEM_TYPE_64) + region->start |= (u64)zdev->bars[j + 1].val << 32; + + region->end = region->start + (1UL << zbar->size) - 1; + return; + } + } +} + +void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res, + struct pci_bus_region *region) +{ + struct zpci_bus *zbus = bus->sysdata; + struct zpci_dev *zdev; + resource_size_t start, end; + + res->start = region->start; + res->end = region->end; + + for (int i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) { + zdev = zbus->function[i]; + if (!zdev || !zdev->has_resources) + continue; + + for (int j = 0; j < PCI_STD_NUM_BARS; j++) { + if (!zdev->bars[j].size) + continue; + + /* only MMIO is supported */ + start = zdev->bars[j].val & PCI_BASE_ADDRESS_MEM_MASK; + if (zdev->bars[j].val & PCI_BASE_ADDRESS_MEM_TYPE_64) + start |= (u64)zdev->bars[j + 1].val << 32; + + end = start + (1UL << zdev->bars[j].size) - 1; + + if (start == region->start && end == region->end) { + res->start = zdev->bars[j].res->start; + res->end = zdev->bars[j].res->end; + return; + } + } + } +} + void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size, pgprot_t prot) { diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c index afa50b446567..56d62afb3afe 100644 --- a/drivers/pci/host-bridge.c +++ b/drivers/pci/host-bridge.c @@ -48,7 +48,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge, } EXPORT_SYMBOL_GPL(pci_set_host_bridge_release); -void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, +void __weak pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, struct resource *res) { struct pci_host_bridge *bridge = pci_find_host_bridge(bus); @@ -73,7 +73,7 @@ static bool region_contains(struct pci_bus_region *region1, return region1->start <= region2->start && region1->end >= region2->end; } -void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res, +void __weak pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res, struct pci_bus_region *region) { struct pci_host_bridge *bridge = pci_find_host_bridge(bus); -- 2.43.0[PATCH v2 2/2] s390/pci: Add architecture specific resource/bus address translationFarhan Ali undefinedlinux-s390@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org undefined undefined undefined undefined undefined undefined undefined undefined undefined undefined