Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6bd101b authored by Keith Busch's avatar Keith Busch Committed by Bjorn Helgaas
Browse files

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: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarSinan Kaya <okaya@kernel.org>
parent 7b42d97e
Loading
Loading
Loading
Loading
+55 −5
Original line number Diff line number Diff line
@@ -295,21 +295,71 @@ struct pci_sriov {
	bool		drivers_autoprobe; /* Auto probing of VFs by driver */
};

/* pci_dev priv_flags */
#define PCI_DEV_DISCONNECTED 0
#define PCI_DEV_ADDED 1
/**
 * pci_dev_set_io_state - Set the new error state if possible.
 *
 * @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)
{
	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;
}

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)
{
	assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added);
+4 −6
Original line number Diff line number Diff line
@@ -52,9 +52,8 @@ static int report_error_detected(struct pci_dev *dev,
	const struct pci_error_handlers *err_handler;

	device_lock(&dev->dev);
	dev->error_state = state;

	if (!dev->driver ||
	if (!pci_dev_set_io_state(dev, state) ||
		!dev->driver ||
		!dev->driver->err_handler ||
		!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;

	device_lock(&dev->dev);
	dev->error_state = pci_channel_io_normal;

	if (!dev->driver ||
	if (!pci_dev_set_io_state(dev, pci_channel_io_normal) ||
		!dev->driver ||
		!dev->driver->err_handler ||
		!dev->driver->err_handler->resume)
		goto out;