diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2023-02-22 13:47:25 -0600 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2023-02-22 13:47:25 -0600 |
commit | fec93576f7dc80756c6f142a3312ddc4dac5db9a (patch) | |
tree | bd8206b90305edd1677843b221d3cb3ca88145e3 /drivers/pci | |
parent | a17613298f5df5bfaf66b403ed082da93abc05ce (diff) | |
parent | 74ff8864cc842be994853095dba6db48e716400a (diff) | |
download | lwn-fec93576f7dc80756c6f142a3312ddc4dac5db9a.tar.gz lwn-fec93576f7dc80756c6f142a3312ddc4dac5db9a.zip |
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
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci.h | 43 |
2 files changed, 15 insertions, 30 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 10e9670eea0b..f8c70115b691 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -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, diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 9ed3b5550043..5d5a44aaafe8 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -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) { - case pci_channel_io_frozen: - case pci_channel_io_normal: - case pci_channel_io_perm_failure: - changed = true; - break; - } - break; + xchg(&dev->error_state, pci_channel_io_perm_failure); + return true; case pci_channel_io_frozen: - 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_normal, + pci_channel_io_frozen); + return old != pci_channel_io_perm_failure; 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; } |