diff options
author | Jon Derrick <jonathan.derrick@intel.com> | 2018-05-18 15:28:00 -0400 |
---|---|---|
committer | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2018-05-24 12:43:19 -0400 |
commit | 2a5a9c9a20f919c33bb315dab2867992ec96dfa4 (patch) | |
tree | ccffc149c89d1f0a88ed90ff9cba780190fb8102 | |
parent | 6788958e4f3ca1b75df841d7e25951807e94e5e0 (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.c | 34 |
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); |