forked from mirrors/linux
		
	PCI: Unify device inaccessible
Bring surprise removals and permanent failures together so we no longer need separate flags. The implementation enforces that error handling will not be able to override a surprise removal's permanent channel failure. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Sinan Kaya <okaya@kernel.org>
This commit is contained in:
		
							parent
							
								
									7b42d97e99
								
							
						
					
					
						commit
						a6bd101b8f
					
				
					 2 changed files with 59 additions and 11 deletions
				
			
		| 
						 | 
					@ -295,21 +295,71 @@ struct pci_sriov {
 | 
				
			||||||
	bool		drivers_autoprobe; /* Auto probing of VFs by driver */
 | 
						bool		drivers_autoprobe; /* Auto probing of VFs by driver */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* pci_dev priv_flags */
 | 
					/**
 | 
				
			||||||
#define PCI_DEV_DISCONNECTED 0
 | 
					 * pci_dev_set_io_state - Set the new error state if possible.
 | 
				
			||||||
#define PCI_DEV_ADDED 1
 | 
					 *
 | 
				
			||||||
 | 
					 * @dev - pci device to set new error_state
 | 
				
			||||||
 | 
					 * @new - the state we want dev to be in
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Must be called with device_lock held.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns true if state has been changed to the requested state.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline bool pci_dev_set_io_state(struct pci_dev *dev,
 | 
				
			||||||
 | 
										pci_channel_state_t new)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool changed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						device_lock_assert(&dev->dev);
 | 
				
			||||||
 | 
						switch (new) {
 | 
				
			||||||
 | 
						case pci_channel_io_perm_failure:
 | 
				
			||||||
 | 
							switch (dev->error_state) {
 | 
				
			||||||
 | 
							case pci_channel_io_frozen:
 | 
				
			||||||
 | 
							case pci_channel_io_normal:
 | 
				
			||||||
 | 
							case pci_channel_io_perm_failure:
 | 
				
			||||||
 | 
								changed = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case pci_channel_io_frozen:
 | 
				
			||||||
 | 
							switch (dev->error_state) {
 | 
				
			||||||
 | 
							case pci_channel_io_frozen:
 | 
				
			||||||
 | 
							case pci_channel_io_normal:
 | 
				
			||||||
 | 
								changed = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case pci_channel_io_normal:
 | 
				
			||||||
 | 
							switch (dev->error_state) {
 | 
				
			||||||
 | 
							case pci_channel_io_frozen:
 | 
				
			||||||
 | 
							case pci_channel_io_normal:
 | 
				
			||||||
 | 
								changed = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (changed)
 | 
				
			||||||
 | 
							dev->error_state = new;
 | 
				
			||||||
 | 
						return changed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
 | 
					static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	set_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
 | 
						device_lock(&dev->dev);
 | 
				
			||||||
 | 
						pci_dev_set_io_state(dev, pci_channel_io_perm_failure);
 | 
				
			||||||
 | 
						device_unlock(&dev->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
 | 
					static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
 | 
						return dev->error_state == pci_channel_io_perm_failure;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* pci_dev priv_flags */
 | 
				
			||||||
 | 
					#define PCI_DEV_ADDED 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void pci_dev_assign_added(struct pci_dev *dev, bool added)
 | 
					static inline void pci_dev_assign_added(struct pci_dev *dev, bool added)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added);
 | 
						assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,9 +52,8 @@ static int report_error_detected(struct pci_dev *dev,
 | 
				
			||||||
	const struct pci_error_handlers *err_handler;
 | 
						const struct pci_error_handlers *err_handler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_lock(&dev->dev);
 | 
						device_lock(&dev->dev);
 | 
				
			||||||
	dev->error_state = state;
 | 
						if (!pci_dev_set_io_state(dev, state) ||
 | 
				
			||||||
 | 
							!dev->driver ||
 | 
				
			||||||
	if (!dev->driver ||
 | 
					 | 
				
			||||||
		!dev->driver->err_handler ||
 | 
							!dev->driver->err_handler ||
 | 
				
			||||||
		!dev->driver->err_handler->error_detected) {
 | 
							!dev->driver->err_handler->error_detected) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
| 
						 | 
					@ -130,9 +129,8 @@ static int report_resume(struct pci_dev *dev, void *data)
 | 
				
			||||||
	const struct pci_error_handlers *err_handler;
 | 
						const struct pci_error_handlers *err_handler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device_lock(&dev->dev);
 | 
						device_lock(&dev->dev);
 | 
				
			||||||
	dev->error_state = pci_channel_io_normal;
 | 
						if (!pci_dev_set_io_state(dev, pci_channel_io_normal) ||
 | 
				
			||||||
 | 
							!dev->driver ||
 | 
				
			||||||
	if (!dev->driver ||
 | 
					 | 
				
			||||||
		!dev->driver->err_handler ||
 | 
							!dev->driver->err_handler ||
 | 
				
			||||||
		!dev->driver->err_handler->resume)
 | 
							!dev->driver->err_handler->resume)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue