PCI: vmd: Fix secondary bus reset for Intel bridges
[ Upstream commit 0a584655ef89541dae4d48d2c523b1480ae80284 ] 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: 6aab5622296b ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
6c8319b90f
commit
38c1d5d2f8
@ -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 membar2_offset = 0x2000;
|
||||
struct pci_bus *child;
|
||||
struct pci_dev *dev;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -859,8 +860,25 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
|
||||
|
||||
pci_scan_child_bus(vmd->bus);
|
||||
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);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user