PCI: vmd: Fix secondary bus reset for Intel bridges
The reset was never applied in the current implementation because Intel
Bridges owned by VMD are parentless. Internally, pci_reset_bus() applies
a reset to the parent of the PCI device supplied as argument, but in this
case it failed because there wasn't a parent.
In more detail, this change allows the VMD driver to enumerate NVMe devices
in pass-through configurations when guest reboots are performed. There was
an attempted to fix this, but later we discovered that the code inside
pci_reset_bus() wasn’t triggering secondary bus resets. Therefore, we
updated the parameters passed to it, and now NVMe SSDs attached to VMD
bridges are properly enumerated in VT-d pass-through scenarios.
Link: https://lore.kernel.org/r/20221206001637.4744-1-francisco.munoz.ruiz@linux.intel.com
Fixes: 6aab562229
("PCI: vmd: Clean up domain before enumeration")
Signed-off-by: Francisco Munoz <francisco.munoz.ruiz@linux.intel.com>
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Reviewed-by: Nirmal Patel <nirmal.patel@linux.intel.com>
Reviewed-by: Jonathan Derrick <jonathan.derrick@linux.dev>
This commit is contained in:
parent
d899aa6684
commit
0a584655ef
1 changed files with 20 additions and 2 deletions
|
@ -719,6 +719,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
||||||
resource_size_t offset[2] = {0};
|
resource_size_t offset[2] = {0};
|
||||||
resource_size_t membar2_offset = 0x2000;
|
resource_size_t membar2_offset = 0x2000;
|
||||||
struct pci_bus *child;
|
struct pci_bus *child;
|
||||||
|
struct pci_dev *dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -859,8 +860,25 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
||||||
|
|
||||||
pci_scan_child_bus(vmd->bus);
|
pci_scan_child_bus(vmd->bus);
|
||||||
vmd_domain_reset(vmd);
|
vmd_domain_reset(vmd);
|
||||||
list_for_each_entry(child, &vmd->bus->children, node)
|
|
||||||
pci_reset_bus(child->self);
|
/* When Intel VMD is enabled, the OS does not discover the Root Ports
|
||||||
|
* owned by Intel VMD within the MMCFG space. pci_reset_bus() applies
|
||||||
|
* a reset to the parent of the PCI device supplied as argument. This
|
||||||
|
* is why we pass a child device, so the reset can be triggered at
|
||||||
|
* the Intel bridge level and propagated to all the children in the
|
||||||
|
* hierarchy.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(child, &vmd->bus->children, node) {
|
||||||
|
if (!list_empty(&child->devices)) {
|
||||||
|
dev = list_first_entry(&child->devices,
|
||||||
|
struct pci_dev, bus_list);
|
||||||
|
if (pci_reset_bus(dev))
|
||||||
|
pci_warn(dev, "can't reset device: %d\n", ret);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pci_assign_unassigned_bus_resources(vmd->bus);
|
pci_assign_unassigned_bus_resources(vmd->bus);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue