Commit fec93576 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/hotplug'

- Add quirk to work around Qualcomm hardware defect in Command Completed
  signaling (Manivannan Sadhasivam)

- Remove locking to allow devices to be marked as disconnected immediately
  instead of waiting for concurrent bind/unbind to complete (Lukas Wunner)

* pci/hotplug:
  PCI: hotplug: Allow marking devices as disconnected during bind/unbind
  PCI: pciehp: Add Qualcomm quirk for Command Completed erratum
parents a1761329 74ff8864
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1088,6 +1088,8 @@ static void quirk_cmd_compl(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
			      PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x010e,
			      PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0110,
			      PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0400,
+13 −30
Original line number Diff line number Diff line
@@ -310,53 +310,36 @@ struct pci_sriov {
 * @dev: PCI device to set new error_state
 * @new: the state we want dev to be in
 *
 * Must be called with device_lock held.
 * If the device is experiencing perm_failure, it has to remain in that state.
 * Any other transition is allowed.
 *
 * 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;
	pci_channel_state_t old;

	device_lock_assert(&dev->dev);
	switch (new) {
	case pci_channel_io_perm_failure:
		switch (dev->error_state) {
		xchg(&dev->error_state, pci_channel_io_perm_failure);
		return true;
	case pci_channel_io_frozen:
		old = cmpxchg(&dev->error_state, pci_channel_io_normal,
			      pci_channel_io_frozen);
		return old != pci_channel_io_perm_failure;
	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;
		old = cmpxchg(&dev->error_state, pci_channel_io_frozen,
			      pci_channel_io_normal);
		return old != pci_channel_io_perm_failure;
	default:
		return false;
	}
	if (changed)
		dev->error_state = new;
	return changed;
}

static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
{
	device_lock(&dev->dev);
	pci_dev_set_io_state(dev, pci_channel_io_perm_failure);
	device_unlock(&dev->dev);

	return 0;
}