]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PCI: vmd: Add offset to bus numbers if necessary
authorJon Derrick <jonathan.derrick@intel.com>
Fri, 18 May 2018 19:28:00 +0000 (13:28 -0600)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 24 May 2018 16:43:19 +0000 (17:43 +0100)
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>
drivers/pci/host/vmd.c

index 1544121b74f37bbc7513ed68837720a21b215ef9..34fa6cf0b0eea23ad83ba5468f785c3d8355c3a0 100644 (file)
 #define VMD_MEMBAR1    2
 #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 MB2_SHADOW_EN(vmlock)  (vmlock & 0x2)
 
@@ -34,6 +38,12 @@ enum vmd_features {
         * resource assignment to enable guest virtualization
         */
        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;
        LIST_HEAD(resources);
        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
@@ -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];
        vmd->resources[0] = (struct resource) {
                .name  = "VMD CFGBAR",
-               .start = 0,
-               .end   = (resource_size(res) >> 20) - 1,
+               .start = busn_start,
+               .end   = busn_start + (resource_size(res) >> 20) - 1,
                .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[2], offset[1]);
 
-       vmd->bus = pci_create_root_bus(&vmd->dev->dev, 0, &vmd_ops, sd,
-                                      &resources);
+       vmd->bus = pci_create_root_bus(&vmd->dev->dev, busn_start, &vmd_ops,
+                                      sd, &resources);
        if (!vmd->bus) {
                pci_free_resource_list(&resources);
                irq_domain_remove(vmd->irq_domain);