--- /dev/null
+From e3dffa4f6c3612dea337c9c59191bd418afc941b Mon Sep 17 00:00:00 2001
+From: Jon Derrick <jonathan.derrick@intel.com>
+Date: Mon, 16 Sep 2019 07:54:34 -0600
+Subject: PCI: vmd: Fix config addressing when using bus offsets
+
+From: Jon Derrick <jonathan.derrick@intel.com>
+
+commit e3dffa4f6c3612dea337c9c59191bd418afc941b upstream.
+
+VMD maps child device config spaces to the VMD Config BAR linearly
+regardless of the starting bus offset. Because of this, the config
+address decode must ignore starting bus offsets when mapping the BDF to
+the config space address.
+
+Fixes: 2a5a9c9a20f9 ("PCI: vmd: Add offset to bus numbers if necessary")
+Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org # v5.2+
+Signed-off-by: Sushma Kalakota <sushmax.kalakota@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/controller/vmd.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/controller/vmd.c
++++ b/drivers/pci/controller/vmd.c
+@@ -97,6 +97,7 @@ struct vmd_dev {
+ struct resource resources[3];
+ struct irq_domain *irq_domain;
+ struct pci_bus *bus;
++ u8 busn_start;
+
+ #ifdef CONFIG_X86_DEV_DMA_OPS
+ struct dma_map_ops dma_ops;
+@@ -468,7 +469,8 @@ static char __iomem *vmd_cfg_addr(struct
+ unsigned int devfn, int reg, int len)
+ {
+ char __iomem *addr = vmd->cfgbar +
+- (bus->number << 20) + (devfn << 12) + reg;
++ ((bus->number - vmd->busn_start) << 20) +
++ (devfn << 12) + reg;
+
+ if ((addr - vmd->cfgbar) + len >=
+ resource_size(&vmd->dev->resource[VMD_CFGBAR]))
+@@ -591,7 +593,7 @@ static int vmd_enable_domain(struct vmd_
+ unsigned long flags;
+ LIST_HEAD(resources);
+ resource_size_t offset[2] = {0};
+- resource_size_t membar2_offset = 0x2000, busn_start = 0;
++ resource_size_t membar2_offset = 0x2000;
+
+ /*
+ * Shadow registers may exist in certain VMD device ids which allow
+@@ -633,14 +635,14 @@ static int vmd_enable_domain(struct vmd_
+ pci_read_config_dword(vmd->dev, PCI_REG_VMCONFIG, &vmconfig);
+ if (BUS_RESTRICT_CAP(vmcap) &&
+ (BUS_RESTRICT_CFG(vmconfig) == 0x1))
+- busn_start = 128;
++ vmd->busn_start = 128;
+ }
+
+ res = &vmd->dev->resource[VMD_CFGBAR];
+ vmd->resources[0] = (struct resource) {
+ .name = "VMD CFGBAR",
+- .start = busn_start,
+- .end = busn_start + (resource_size(res) >> 20) - 1,
++ .start = vmd->busn_start,
++ .end = vmd->busn_start + (resource_size(res) >> 20) - 1,
+ .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
+ };
+
+@@ -708,8 +710,8 @@ static int vmd_enable_domain(struct vmd_
+ pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
+ pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
+
+- vmd->bus = pci_create_root_bus(&vmd->dev->dev, busn_start, &vmd_ops,
+- sd, &resources);
++ vmd->bus = pci_create_root_bus(&vmd->dev->dev, vmd->busn_start,
++ &vmd_ops, sd, &resources);
+ if (!vmd->bus) {
+ pci_free_resource_list(&resources);
+ irq_domain_remove(vmd->irq_domain);