mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	PCI/ERR: Use slot reset if available
The secondary bus reset may have link side effects that a hotplug capable port may incorrectly react to. Use the slot specific reset for hotplug ports, fixing the undesirable link down-up handling during error recovering. Signed-off-by: Keith Busch <keith.busch@intel.com> [bhelgaas: fold in https://lore.kernel.org/linux-pci/20180926152326.14821-1-keith.busch@intel.com for issue reported by Stephen Rothwell <sfr@canb.auug.org.au>] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Sinan Kaya <okaya@kernel.org>
This commit is contained in:
		
							parent
							
								
									9d938ea53b
								
							
						
					
					
						commit
						c4eed62a21
					
				
					 5 changed files with 41 additions and 3 deletions
				
			
		|  | @ -35,6 +35,8 @@ | |||
| #include <linux/aer.h> | ||||
| #include "pci.h" | ||||
| 
 | ||||
| DEFINE_MUTEX(pci_slot_mutex); | ||||
| 
 | ||||
| const char *pci_power_names[] = { | ||||
| 	"error", "D0", "D1", "D2", "D3hot", "D3cold", "unknown", | ||||
| }; | ||||
|  | @ -5155,6 +5157,41 @@ static int pci_bus_reset(struct pci_bus *bus, int probe) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * pci_bus_error_reset - reset the bridge's subordinate bus | ||||
|  * @bridge: The parent device that connects to the bus to reset | ||||
|  * | ||||
|  * This function will first try to reset the slots on this bus if the method is | ||||
|  * available. If slot reset fails or is not available, this will fall back to a | ||||
|  * secondary bus reset. | ||||
|  */ | ||||
| int pci_bus_error_reset(struct pci_dev *bridge) | ||||
| { | ||||
| 	struct pci_bus *bus = bridge->subordinate; | ||||
| 	struct pci_slot *slot; | ||||
| 
 | ||||
| 	if (!bus) | ||||
| 		return -ENOTTY; | ||||
| 
 | ||||
| 	mutex_lock(&pci_slot_mutex); | ||||
| 	if (list_empty(&bus->slots)) | ||||
| 		goto bus_reset; | ||||
| 
 | ||||
| 	list_for_each_entry(slot, &bus->slots, list) | ||||
| 		if (pci_probe_reset_slot(slot)) | ||||
| 			goto bus_reset; | ||||
| 
 | ||||
| 	list_for_each_entry(slot, &bus->slots, list) | ||||
| 		if (pci_slot_reset(slot, 0)) | ||||
| 			goto bus_reset; | ||||
| 
 | ||||
| 	mutex_unlock(&pci_slot_mutex); | ||||
| 	return 0; | ||||
| bus_reset: | ||||
| 	mutex_unlock(&pci_slot_mutex); | ||||
| 	return pci_bus_reset(bridge->subordinate, 0); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * pci_probe_reset_bus - probe whether a PCI bus can be reset | ||||
|  * @bus: PCI bus to probe | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai, | |||
| 
 | ||||
| int pci_probe_reset_function(struct pci_dev *dev); | ||||
| int pci_bridge_secondary_bus_reset(struct pci_dev *dev); | ||||
| int pci_bus_error_reset(struct pci_dev *dev); | ||||
| 
 | ||||
| /**
 | ||||
|  * struct pci_platform_pm_ops - Firmware PM callbacks | ||||
|  | @ -136,6 +137,7 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; } | |||
| 
 | ||||
| /* Lock for read/write access to pci device and bus lists */ | ||||
| extern struct rw_semaphore pci_bus_sem; | ||||
| extern struct mutex pci_slot_mutex; | ||||
| 
 | ||||
| extern raw_spinlock_t pci_lock; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1528,7 +1528,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) | |||
| 	reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; | ||||
| 	pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); | ||||
| 
 | ||||
| 	rc = pci_bridge_secondary_bus_reset(dev); | ||||
| 	rc = pci_bus_error_reset(dev); | ||||
| 	pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n"); | ||||
| 
 | ||||
| 	/* Clear Root Error Status */ | ||||
|  |  | |||
|  | @ -177,7 +177,7 @@ static pci_ers_result_t default_reset_link(struct pci_dev *dev) | |||
| { | ||||
| 	int rc; | ||||
| 
 | ||||
| 	rc = pci_bridge_secondary_bus_reset(dev); | ||||
| 	rc = pci_bus_error_reset(dev); | ||||
| 	pci_printk(KERN_DEBUG, dev, "downstream link has been reset\n"); | ||||
| 	return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; | ||||
| } | ||||
|  |  | |||
|  | @ -14,7 +14,6 @@ | |||
| 
 | ||||
| struct kset *pci_slots_kset; | ||||
| EXPORT_SYMBOL_GPL(pci_slots_kset); | ||||
| static DEFINE_MUTEX(pci_slot_mutex); | ||||
| 
 | ||||
| static ssize_t pci_slot_attr_show(struct kobject *kobj, | ||||
| 					struct attribute *attr, char *buf) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Keith Busch
						Keith Busch