Merge branch 'remotes/lorenzo/pci/vmd'

- Reset everything below VMD before enumerating to work around failure to
  enumerate NVMe devices when guest OS reboots (Nirmal Patel)

- Honor platform ACPI _OSC feature negotiation for Root Ports below VMD
  (Kai-Heng Feng)

- Add support for Raptor Lake SKUs (Karthik L Gopalakrishnan)

* remotes/lorenzo/pci/vmd:
  PCI: vmd: Add DID 8086:A77F for all Intel Raptor Lake SKU's
  PCI: vmd: Honor ACPI _OSC on PCIe features
  PCI: vmd: Clean up domain before enumeration
This commit is contained in:
Bjorn Helgaas 2022-01-13 09:57:50 -06:00
commit ec5d85e7f0

View File

@ -501,6 +501,40 @@ static inline void vmd_acpi_begin(void) { }
static inline void vmd_acpi_end(void) { }
#endif /* CONFIG_ACPI */
static void vmd_domain_reset(struct vmd_dev *vmd)
{
u16 bus, max_buses = resource_size(&vmd->resources[0]);
u8 dev, functions, fn, hdr_type;
char __iomem *base;
for (bus = 0; bus < max_buses; bus++) {
for (dev = 0; dev < 32; dev++) {
base = vmd->cfgbar + PCIE_ECAM_OFFSET(bus,
PCI_DEVFN(dev, 0), 0);
hdr_type = readb(base + PCI_HEADER_TYPE) &
PCI_HEADER_TYPE_MASK;
functions = (hdr_type & 0x80) ? 8 : 1;
for (fn = 0; fn < functions; fn++) {
base = vmd->cfgbar + PCIE_ECAM_OFFSET(bus,
PCI_DEVFN(dev, fn), 0);
hdr_type = readb(base + PCI_HEADER_TYPE) &
PCI_HEADER_TYPE_MASK;
if (hdr_type != PCI_HEADER_TYPE_BRIDGE ||
(readw(base + PCI_CLASS_DEVICE) !=
PCI_CLASS_BRIDGE_PCI))
continue;
memset_io(base + PCI_IO_BASE, 0,
PCI_ROM_ADDRESS1 - PCI_IO_BASE);
}
}
}
}
static void vmd_attach_resources(struct vmd_dev *vmd)
{
vmd->dev->resource[VMD_MEMBAR1].child = &vmd->resources[1];
@ -661,6 +695,21 @@ static int vmd_alloc_irqs(struct vmd_dev *vmd)
return 0;
}
/*
* Since VMD is an aperture to regular PCIe root ports, only allow it to
* control features that the OS is allowed to control on the physical PCI bus.
*/
static void vmd_copy_host_bridge_flags(struct pci_host_bridge *root_bridge,
struct pci_host_bridge *vmd_bridge)
{
vmd_bridge->native_pcie_hotplug = root_bridge->native_pcie_hotplug;
vmd_bridge->native_shpc_hotplug = root_bridge->native_shpc_hotplug;
vmd_bridge->native_aer = root_bridge->native_aer;
vmd_bridge->native_pme = root_bridge->native_pme;
vmd_bridge->native_ltr = root_bridge->native_ltr;
vmd_bridge->native_dpc = root_bridge->native_dpc;
}
static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
{
struct pci_sysdata *sd = &vmd->sysdata;
@ -798,6 +847,9 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
return -ENODEV;
}
vmd_copy_host_bridge_flags(pci_find_host_bridge(vmd->dev->bus),
to_pci_host_bridge(vmd->bus->bridge));
vmd_attach_resources(vmd);
if (vmd->irq_domain)
dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
@ -805,6 +857,9 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
vmd_acpi_begin();
pci_scan_child_bus(vmd->bus);
vmd_domain_reset(vmd);
list_for_each_entry(child, &vmd->bus->children, node)
pci_reset_bus(child->self);
pci_assign_unassigned_bus_resources(vmd->bus);
/*
@ -953,6 +1008,10 @@ static const struct pci_device_id vmd_ids[] = {
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
VMD_FEAT_HAS_BUS_RESTRICTIONS |
VMD_FEAT_OFFSET_FIRST_VECTOR,},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa77f),
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
VMD_FEAT_HAS_BUS_RESTRICTIONS |
VMD_FEAT_OFFSET_FIRST_VECTOR,},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
VMD_FEAT_HAS_BUS_RESTRICTIONS |