aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2018-06-06 17:10:45 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-06-06 17:10:45 -0400
commit73144d77cb87d60b4bcab6992a62d6787b09dcf0 (patch)
treedb9fb81f63d8aa098bb3001573744e7a9d417a49
parente52d38f4abf49f8b63a6ad0ce21e5f495c15897f (diff)
parentd260d34e318f7ee1960d1bd9473afff0dd7be2c7 (diff)
Merge branch 'lorenzo/pci/vmd'
- support VMD "membar shadow" feature (Jon Derrick) - support VMD bus number offsets (Jon Derrick) - add VMD "no AER source ID" quirk for more device IDs (Jon Derrick) * lorenzo/pci/vmd: PCI: vmd: Add an additional VMD device id to driver device id table x86/PCI: Add additional VMD device root ports to VMD AER quirk PCI: vmd: Add offset to bus numbers if necessary PCI: vmd: Assign membar addresses from shadow registers PCI: Add Intel VMD devices to pci ids
-rw-r--r--arch/x86/pci/fixup.c4
-rw-r--r--drivers/pci/host/vmd.c91
-rw-r--r--include/linux/pci_ids.h2
3 files changed, 87 insertions, 10 deletions
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 54ef19e90705..13f4485ca388 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -636,6 +636,10 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid);
636DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); 636DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid);
637DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); 637DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid);
638DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); 638DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid);
639DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334a, quirk_no_aersid);
640DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334b, quirk_no_aersid);
641DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334c, quirk_no_aersid);
642DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334d, quirk_no_aersid);
639 643
640#ifdef CONFIG_PHYS_ADDR_T_64BIT 644#ifdef CONFIG_PHYS_ADDR_T_64BIT
641 645
diff --git a/drivers/pci/host/vmd.c b/drivers/pci/host/vmd.c
index 930a8fa08bd6..942b64fc7f1f 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/host/vmd.c
@@ -24,6 +24,28 @@
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)
31#define PCI_REG_VMLOCK 0x70
32#define MB2_SHADOW_EN(vmlock) (vmlock & 0x2)
33
34enum vmd_features {
35 /*
36 * Device may contain registers which hint the physical location of the
37 * membars, in order to allow proper address translation during
38 * resource assignment to enable guest virtualization
39 */
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),
47};
48
27/* 49/*
28 * Lock for manipulating VMD IRQ lists. 50 * Lock for manipulating VMD IRQ lists.
29 */ 51 */
@@ -546,7 +568,7 @@ static int vmd_find_free_domain(void)
546 return domain + 1; 568 return domain + 1;
547} 569}
548 570
549static int vmd_enable_domain(struct vmd_dev *vmd) 571static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
550{ 572{
551 struct pci_sysdata *sd = &vmd->sysdata; 573 struct pci_sysdata *sd = &vmd->sysdata;
552 struct fwnode_handle *fn; 574 struct fwnode_handle *fn;
@@ -554,12 +576,57 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
554 u32 upper_bits; 576 u32 upper_bits;
555 unsigned long flags; 577 unsigned long flags;
556 LIST_HEAD(resources); 578 LIST_HEAD(resources);
579 resource_size_t offset[2] = {0};
580 resource_size_t membar2_offset = 0x2000, busn_start = 0;
581
582 /*
583 * Shadow registers may exist in certain VMD device ids which allow
584 * guests to correctly assign host physical addresses to the root ports
585 * and child devices. These registers will either return the host value
586 * or 0, depending on an enable bit in the VMD device.
587 */
588 if (features & VMD_FEAT_HAS_MEMBAR_SHADOW) {
589 u32 vmlock;
590 int ret;
591
592 membar2_offset = 0x2018;
593 ret = pci_read_config_dword(vmd->dev, PCI_REG_VMLOCK, &vmlock);
594 if (ret || vmlock == ~0)
595 return -ENODEV;
596
597 if (MB2_SHADOW_EN(vmlock)) {
598 void __iomem *membar2;
599
600 membar2 = pci_iomap(vmd->dev, VMD_MEMBAR2, 0);
601 if (!membar2)
602 return -ENOMEM;
603 offset[0] = vmd->dev->resource[VMD_MEMBAR1].start -
604 readq(membar2 + 0x2008);
605 offset[1] = vmd->dev->resource[VMD_MEMBAR2].start -
606 readq(membar2 + 0x2010);
607 pci_iounmap(vmd->dev, membar2);
608 }
609 }
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 }
557 624
558 res = &vmd->dev->resource[VMD_CFGBAR]; 625 res = &vmd->dev->resource[VMD_CFGBAR];
559 vmd->resources[0] = (struct resource) { 626 vmd->resources[0] = (struct resource) {
560 .name = "VMD CFGBAR", 627 .name = "VMD CFGBAR",
561 .start = 0, 628 .start = busn_start,
562 .end = (resource_size(res) >> 20) - 1, 629 .end = busn_start + (resource_size(res) >> 20) - 1,
563 .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED, 630 .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
564 }; 631 };
565 632
@@ -600,7 +667,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
600 flags &= ~IORESOURCE_MEM_64; 667 flags &= ~IORESOURCE_MEM_64;
601 vmd->resources[2] = (struct resource) { 668 vmd->resources[2] = (struct resource) {
602 .name = "VMD MEMBAR2", 669 .name = "VMD MEMBAR2",
603 .start = res->start + 0x2000, 670 .start = res->start + membar2_offset,
604 .end = res->end, 671 .end = res->end,
605 .flags = flags, 672 .flags = flags,
606 .parent = res, 673 .parent = res,
@@ -624,10 +691,11 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
624 return -ENODEV; 691 return -ENODEV;
625 692
626 pci_add_resource(&resources, &vmd->resources[0]); 693 pci_add_resource(&resources, &vmd->resources[0]);
627 pci_add_resource(&resources, &vmd->resources[1]); 694 pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
628 pci_add_resource(&resources, &vmd->resources[2]); 695 pci_add_resource_offset(&resources, &vmd->resources[2], offset[1]);
629 vmd->bus = pci_create_root_bus(&vmd->dev->dev, 0, &vmd_ops, sd, 696
630 &resources); 697 vmd->bus = pci_create_root_bus(&vmd->dev->dev, busn_start, &vmd_ops,
698 sd, &resources);
631 if (!vmd->bus) { 699 if (!vmd->bus) {
632 pci_free_resource_list(&resources); 700 pci_free_resource_list(&resources);
633 irq_domain_remove(vmd->irq_domain); 701 irq_domain_remove(vmd->irq_domain);
@@ -713,7 +781,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
713 781
714 spin_lock_init(&vmd->cfg_lock); 782 spin_lock_init(&vmd->cfg_lock);
715 pci_set_drvdata(dev, vmd); 783 pci_set_drvdata(dev, vmd);
716 err = vmd_enable_domain(vmd); 784 err = vmd_enable_domain(vmd, (unsigned long) id->driver_data);
717 if (err) 785 if (err)
718 return err; 786 return err;
719 787
@@ -778,7 +846,10 @@ static int vmd_resume(struct device *dev)
778static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume); 846static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume);
779 847
780static const struct pci_device_id vmd_ids[] = { 848static const struct pci_device_id vmd_ids[] = {
781 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x201d),}, 849 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D),},
850 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
851 .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
852 VMD_FEAT_HAS_BUS_RESTRICTIONS,},
782 {0,} 853 {0,}
783}; 854};
784MODULE_DEVICE_TABLE(pci, vmd_ids); 855MODULE_DEVICE_TABLE(pci, vmd_ids);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 6e0e0aacdd3e..29502238e510 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2679,6 +2679,7 @@
2679#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31 2679#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31
2680#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40 2680#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40
2681#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f 2681#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f
2682#define PCI_DEVICE_ID_INTEL_VMD_201D 0x201d
2682#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 2683#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310
2683#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f 2684#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f
2684#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 2685#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
@@ -2783,6 +2784,7 @@
2783#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 2784#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815
2784#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e 2785#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
2785#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 2786#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
2787#define PCI_DEVICE_ID_INTEL_VMD_28C0 0x28c0
2786#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910 2788#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
2787#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917 2789#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
2788#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912 2790#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912