PCI: vmd: Add offset to bus numbers if necessary

Depending on platform configuration, certain VMD devices may have an
additional configuration option which specifies the range of bus numbers
allowed in a VMD PCIe domain. We determine this requirement by checking
the value of two vendor specific config registers in the VMD endpoint:

 VMCAP[0] | VMCONFIG[9:8] | Bus Numbers
----------------------------------------
    0     |       *       |     0-255
    1     |      00       |     0-127
    1     |      01       |   128-255
    1     |      10       |     0-255

This feature is also added as a bit in driver_data, to allow future
conforming device ids which support these features to be enabled through
sysfs new_id.

Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
[lorenzo.pieralisi@arm.com: updated commit subject]
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
This commit is contained in:
Jon Derrick 2018-05-18 13:28:00 -06:00 committed by Lorenzo Pieralisi
parent 6788958e4f
commit 2a5a9c9a20

View File

@ -24,6 +24,10 @@
#define VMD_MEMBAR1 2 #define VMD_MEMBAR1 2
#define VMD_MEMBAR2 4 #define VMD_MEMBAR2 4
#define PCI_REG_VMCAP 0x40
#define BUS_RESTRICT_CAP(vmcap) (vmcap & 0x1)
#define PCI_REG_VMCONFIG 0x44
#define BUS_RESTRICT_CFG(vmcfg) ((vmcfg >> 8) & 0x3)
#define PCI_REG_VMLOCK 0x70 #define PCI_REG_VMLOCK 0x70
#define MB2_SHADOW_EN(vmlock) (vmlock & 0x2) #define MB2_SHADOW_EN(vmlock) (vmlock & 0x2)
@ -34,6 +38,12 @@ enum vmd_features {
* resource assignment to enable guest virtualization * resource assignment to enable guest virtualization
*/ */
VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0), VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0),
/*
* Device may provide root port configuration information which limits
* bus numbering
*/
VMD_FEAT_HAS_BUS_RESTRICTIONS = (1 << 1),
}; };
/* /*
@ -567,7 +577,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
unsigned long flags; unsigned long flags;
LIST_HEAD(resources); LIST_HEAD(resources);
resource_size_t offset[2] = {0}; resource_size_t offset[2] = {0};
resource_size_t membar2_offset = 0x2000; resource_size_t membar2_offset = 0x2000, busn_start = 0;
/* /*
* Shadow registers may exist in certain VMD device ids which allow * Shadow registers may exist in certain VMD device ids which allow
@ -598,11 +608,25 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
} }
} }
/*
* Certain VMD devices may have a root port configuration option which
* limits the bus range to between 0-127 or 128-255
*/
if (features & VMD_FEAT_HAS_BUS_RESTRICTIONS) {
u32 vmcap, vmconfig;
pci_read_config_dword(vmd->dev, PCI_REG_VMCAP, &vmcap);
pci_read_config_dword(vmd->dev, PCI_REG_VMCONFIG, &vmconfig);
if (BUS_RESTRICT_CAP(vmcap) &&
(BUS_RESTRICT_CFG(vmconfig) == 0x1))
busn_start = 128;
}
res = &vmd->dev->resource[VMD_CFGBAR]; res = &vmd->dev->resource[VMD_CFGBAR];
vmd->resources[0] = (struct resource) { vmd->resources[0] = (struct resource) {
.name = "VMD CFGBAR", .name = "VMD CFGBAR",
.start = 0, .start = busn_start,
.end = (resource_size(res) >> 20) - 1, .end = busn_start + (resource_size(res) >> 20) - 1,
.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED, .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
}; };
@ -670,8 +694,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[1], offset[0]);
pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]); pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
vmd->bus = pci_create_root_bus(&vmd->dev->dev, 0, &vmd_ops, sd, vmd->bus = pci_create_root_bus(&vmd->dev->dev, busn_start, &vmd_ops,
&resources); sd, &resources);
if (!vmd->bus) { if (!vmd->bus) {
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
irq_domain_remove(vmd->irq_domain); irq_domain_remove(vmd->irq_domain);