diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2018-06-06 17:10:45 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2018-06-06 17:10:45 -0400 |
commit | 73144d77cb87d60b4bcab6992a62d6787b09dcf0 (patch) | |
tree | db9fb81f63d8aa098bb3001573744e7a9d417a49 | |
parent | e52d38f4abf49f8b63a6ad0ce21e5f495c15897f (diff) | |
parent | d260d34e318f7ee1960d1bd9473afff0dd7be2c7 (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.c | 4 | ||||
-rw-r--r-- | drivers/pci/host/vmd.c | 91 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 2 |
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); | |||
636 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); | 636 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); |
637 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); | 637 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); |
638 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); | 638 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); |
639 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334a, quirk_no_aersid); | ||
640 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334b, quirk_no_aersid); | ||
641 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334c, quirk_no_aersid); | ||
642 | DECLARE_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 | |||
34 | enum 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 | ||
549 | static int vmd_enable_domain(struct vmd_dev *vmd) | 571 | static 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) | |||
778 | static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume); | 846 | static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume); |
779 | 847 | ||
780 | static const struct pci_device_id vmd_ids[] = { | 848 | static 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 | }; |
784 | MODULE_DEVICE_TABLE(pci, vmd_ids); | 855 | MODULE_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 |