mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 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…
	
		Reference in a new issue