aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Derrick <jonathan.derrick@intel.com>2018-05-18 15:28:00 -0400
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2018-05-24 12:43:19 -0400
commit2a5a9c9a20f919c33bb315dab2867992ec96dfa4 (patch)
treeccffc149c89d1f0a88ed90ff9cba780190fb8102
parent6788958e4f3ca1b75df841d7e25951807e94e5e0 (diff)
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>
-rw-r--r--drivers/pci/host/vmd.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/pci/host/vmd.c b/drivers/pci/host/vmd.c
index 1544121b74f3..34fa6cf0b0ee 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/host/vmd.c
@@ -24,6 +24,10 @@
24#define VMD_MEMBAR1 2 24#define VMD_MEMBAR1 2
25#define VMD_MEMBAR2 4 25#define VMD_MEMBAR2 4
26 26
27#define PCI_REG_VMCAP 0x40
28#define BUS_RESTRICT_CAP(vmcap) (vmcap & 0x1)
29#define PCI_REG_VMCONFIG 0x44
30#define BUS_RESTRICT_CFG(vmcfg) ((vmcfg >> 8) & 0x3)
27#define PCI_REG_VMLOCK 0x70 31#define PCI_REG_VMLOCK 0x70
28#define MB2_SHADOW_EN(vmlock) (vmlock & 0x2) 32#define MB2_SHADOW_EN(vmlock) (vmlock & 0x2)
29 33
@@ -34,6 +38,12 @@ enum vmd_features {
34 * resource assignment to enable guest virtualization 38 * resource assignment to enable guest virtualization
35 */ 39 */
36 VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0), 40 VMD_FEAT_HAS_MEMBAR_SHADOW = (1 << 0),
41
42 /*
43 * Device may provide root port configuration information which limits
44 * bus numbering
45 */
46 VMD_FEAT_HAS_BUS_RESTRICTIONS = (1 << 1),
37}; 47};
38 48
39/* 49/*
@@ -567,7 +577,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
567 unsigned long flags; 577 unsigned long flags;
568 LIST_HEAD(resources); 578 LIST_HEAD(resources);
569 resource_size_t offset[2] = {0}; 579 resource_size_t offset[2] = {0};
570 resource_size_t membar2_offset = 0x2000; 580 resource_size_t membar2_offset = 0x2000, busn_start = 0;
571 581
572 /* 582 /*
573 * Shadow registers may exist in certain VMD device ids which allow 583 * 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)
598 } 608 }
599 } 609 }
600 610
611 /*
612 * Certain VMD devices may have a root port configuration option which
613 * limits the bus range to between 0-127 or 128-255
614 */
615 if (features & VMD_FEAT_HAS_BUS_RESTRICTIONS) {
616 u32 vmcap, vmconfig;
617
618 pci_read_config_dword(vmd->dev, PCI_REG_VMCAP, &vmcap);
619 pci_read_config_dword(vmd->dev, PCI_REG_VMCONFIG, &vmconfig);
620 if (BUS_RESTRICT_CAP(vmcap) &&
621 (BUS_RESTRICT_CFG(vmconfig) == 0x1))
622 busn_start = 128;
623 }
624
601 res = &vmd->dev->resource[VMD_CFGBAR]; 625 res = &vmd->dev->resource[VMD_CFGBAR];
602 vmd->resources[0] = (struct resource) { 626 vmd->resources[0] = (struct resource) {
603 .name = "VMD CFGBAR", 627 .name = "VMD CFGBAR",
604 .start = 0, 628 .start = busn_start,
605 .end = (resource_size(res) >> 20) - 1, 629 .end = busn_start + (resource_size(res) >> 20) - 1,
606 .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED, 630 .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
607 }; 631 };
608 632
@@ -670,8 +694,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
670 pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]); 694 pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
671 pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]); 695 pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
672 696
673 vmd->bus = pci_create_root_bus(&vmd->dev->dev, 0, &vmd_ops, sd, 697 vmd->bus = pci_create_root_bus(&vmd->dev->dev, busn_start, &vmd_ops,
674 &resources); 698 sd, &resources);
675 if (!vmd->bus) { 699 if (!vmd->bus) {
676 pci_free_resource_list(&resources); 700 pci_free_resource_list(&resources);
677 irq_domain_remove(vmd->irq_domain); 701 irq_domain_remove(vmd->irq_domain);