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
This commit is contained in:
commit
73144d77cb
|
@ -636,6 +636,10 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid);
|
||||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid);
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid);
|
||||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid);
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid);
|
||||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid);
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid);
|
||||||
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334a, quirk_no_aersid);
|
||||||
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334b, quirk_no_aersid);
|
||||||
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334c, quirk_no_aersid);
|
||||||
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x334d, quirk_no_aersid);
|
||||||
|
|
||||||
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,28 @@
|
||||||
#define VMD_MEMBAR1 2
|
#define VMD_MEMBAR1 2
|
||||||
#define VMD_MEMBAR2 4
|
#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)
|
||||||
|
|
||||||
|
enum vmd_features {
|
||||||
|
/*
|
||||||
|
* Device may contain registers which hint the physical location of the
|
||||||
|
* membars, in order to allow proper address translation during
|
||||||
|
* 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),
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lock for manipulating VMD IRQ lists.
|
* Lock for manipulating VMD IRQ lists.
|
||||||
*/
|
*/
|
||||||
|
@ -546,7 +568,7 @@ static int vmd_find_free_domain(void)
|
||||||
return domain + 1;
|
return domain + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmd_enable_domain(struct vmd_dev *vmd)
|
static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
||||||
{
|
{
|
||||||
struct pci_sysdata *sd = &vmd->sysdata;
|
struct pci_sysdata *sd = &vmd->sysdata;
|
||||||
struct fwnode_handle *fn;
|
struct fwnode_handle *fn;
|
||||||
|
@ -554,12 +576,57 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
|
||||||
u32 upper_bits;
|
u32 upper_bits;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
LIST_HEAD(resources);
|
LIST_HEAD(resources);
|
||||||
|
resource_size_t offset[2] = {0};
|
||||||
|
resource_size_t membar2_offset = 0x2000, busn_start = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shadow registers may exist in certain VMD device ids which allow
|
||||||
|
* guests to correctly assign host physical addresses to the root ports
|
||||||
|
* and child devices. These registers will either return the host value
|
||||||
|
* or 0, depending on an enable bit in the VMD device.
|
||||||
|
*/
|
||||||
|
if (features & VMD_FEAT_HAS_MEMBAR_SHADOW) {
|
||||||
|
u32 vmlock;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
membar2_offset = 0x2018;
|
||||||
|
ret = pci_read_config_dword(vmd->dev, PCI_REG_VMLOCK, &vmlock);
|
||||||
|
if (ret || vmlock == ~0)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (MB2_SHADOW_EN(vmlock)) {
|
||||||
|
void __iomem *membar2;
|
||||||
|
|
||||||
|
membar2 = pci_iomap(vmd->dev, VMD_MEMBAR2, 0);
|
||||||
|
if (!membar2)
|
||||||
|
return -ENOMEM;
|
||||||
|
offset[0] = vmd->dev->resource[VMD_MEMBAR1].start -
|
||||||
|
readq(membar2 + 0x2008);
|
||||||
|
offset[1] = vmd->dev->resource[VMD_MEMBAR2].start -
|
||||||
|
readq(membar2 + 0x2010);
|
||||||
|
pci_iounmap(vmd->dev, membar2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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];
|
res = &vmd->dev->resource[VMD_CFGBAR];
|
||||||
vmd->resources[0] = (struct resource) {
|
vmd->resources[0] = (struct resource) {
|
||||||
.name = "VMD CFGBAR",
|
.name = "VMD CFGBAR",
|
||||||
.start = 0,
|
.start = busn_start,
|
||||||
.end = (resource_size(res) >> 20) - 1,
|
.end = busn_start + (resource_size(res) >> 20) - 1,
|
||||||
.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
|
.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -600,7 +667,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
|
||||||
flags &= ~IORESOURCE_MEM_64;
|
flags &= ~IORESOURCE_MEM_64;
|
||||||
vmd->resources[2] = (struct resource) {
|
vmd->resources[2] = (struct resource) {
|
||||||
.name = "VMD MEMBAR2",
|
.name = "VMD MEMBAR2",
|
||||||
.start = res->start + 0x2000,
|
.start = res->start + membar2_offset,
|
||||||
.end = res->end,
|
.end = res->end,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
.parent = res,
|
.parent = res,
|
||||||
|
@ -624,10 +691,11 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
pci_add_resource(&resources, &vmd->resources[0]);
|
pci_add_resource(&resources, &vmd->resources[0]);
|
||||||
pci_add_resource(&resources, &vmd->resources[1]);
|
pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
|
||||||
pci_add_resource(&resources, &vmd->resources[2]);
|
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) {
|
if (!vmd->bus) {
|
||||||
pci_free_resource_list(&resources);
|
pci_free_resource_list(&resources);
|
||||||
irq_domain_remove(vmd->irq_domain);
|
irq_domain_remove(vmd->irq_domain);
|
||||||
|
@ -713,7 +781,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
|
|
||||||
spin_lock_init(&vmd->cfg_lock);
|
spin_lock_init(&vmd->cfg_lock);
|
||||||
pci_set_drvdata(dev, vmd);
|
pci_set_drvdata(dev, vmd);
|
||||||
err = vmd_enable_domain(vmd);
|
err = vmd_enable_domain(vmd, (unsigned long) id->driver_data);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -778,7 +846,10 @@ static int vmd_resume(struct device *dev)
|
||||||
static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume);
|
static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume);
|
||||||
|
|
||||||
static const struct pci_device_id vmd_ids[] = {
|
static const struct pci_device_id vmd_ids[] = {
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x201d),},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_201D),},
|
||||||
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
|
||||||
|
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
|
||||||
|
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
|
||||||
{0,}
|
{0,}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, vmd_ids);
|
MODULE_DEVICE_TABLE(pci, vmd_ids);
|
||||||
|
|
|
@ -2679,6 +2679,7 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31
|
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31
|
||||||
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40
|
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e40
|
||||||
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f
|
#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f
|
||||||
|
#define PCI_DEVICE_ID_INTEL_VMD_201D 0x201d
|
||||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310
|
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310
|
||||||
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f
|
#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f
|
||||||
#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
|
#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
|
||||||
|
@ -2783,6 +2784,7 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815
|
#define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815
|
||||||
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
|
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
|
||||||
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
|
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
|
||||||
|
#define PCI_DEVICE_ID_INTEL_VMD_28C0 0x28c0
|
||||||
#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
|
#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
|
||||||
#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
|
#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
|
||||||
#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
|
#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
|
||||||
|
|
Loading…
Reference in New Issue