| From 3090953a5d12df5b0792d5ab69714c78ea7ba9f9 Mon Sep 17 00:00:00 2001 |
| From: Jon Derrick <jonathan.derrick@intel.com> |
| Date: Mon, 16 Sep 2019 07:54:34 -0600 |
| Subject: [PATCH] PCI: vmd: Fix config addressing when using bus offsets |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c |
| index 999a5509e57e..6c80b9098dd0 100644 |
| --- a/drivers/pci/controller/vmd.c |
| +++ b/drivers/pci/controller/vmd.c |
| @@ -94,6 +94,7 @@ struct vmd_dev { |
| struct resource resources[3]; |
| struct irq_domain *irq_domain; |
| struct pci_bus *bus; |
| + u8 busn_start; |
| |
| struct dma_map_ops dma_ops; |
| struct dma_domain dma_domain; |
| @@ -440,7 +441,8 @@ static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus, |
| 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])) |
| @@ -563,7 +565,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) |
| 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; |
| struct pci_bus *child; |
| |
| /* |
| @@ -606,14 +608,14 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) |
| 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, |
| }; |
| |
| @@ -681,8 +683,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) |
| 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); |
| -- |
| 2.7.4 |
| |