diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2024-11-25 13:40:43 -0600 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2024-11-25 13:40:43 -0600 |
commit | 73bdd7304a0120cf6e6fa3d20cf9e5ef7823f51f (patch) | |
tree | 91f694df71f00472af8607fa8124ecc0b94c627a /drivers | |
parent | d957ff7acaf27674e73db716a2dc0ae8170144cd (diff) | |
parent | 86efc62d031307e53ad4011e0aa8898e029cef47 (diff) | |
download | lwn-73bdd7304a0120cf6e6fa3d20cf9e5ef7823f51f.tar.gz lwn-73bdd7304a0120cf6e6fa3d20cf9e5ef7823f51f.zip |
Merge branch 'pci/doe'
- Wait up to 1 second for DOE Busy bit to clear before writing a request to
the mailbox to avoid failures if the mailbox is still busy from a
previous transfer (Gregory Price)
* pci/doe:
PCI/DOE: Poll DOE Busy bit for up to 1 second in pci_doe_send_req()
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/doe.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/pci/doe.c b/drivers/pci/doe.c index 652d63df9d22..7bd7892c5222 100644 --- a/drivers/pci/doe.c +++ b/drivers/pci/doe.c @@ -146,6 +146,7 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb, { struct pci_dev *pdev = doe_mb->pdev; int offset = doe_mb->cap_offset; + unsigned long timeout_jiffies; size_t length, remainder; u32 val; int i; @@ -155,8 +156,19 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb, * someone other than Linux (e.g. firmware) is using the mailbox. Note * it is expected that firmware and OS will negotiate access rights via * an, as yet to be defined, method. + * + * Wait up to one PCI_DOE_TIMEOUT period to allow the prior command to + * finish. Otherwise, simply error out as unable to field the request. + * + * PCIe r6.2 sec 6.30.3 states no interrupt is raised when the DOE Busy + * bit is cleared, so polling here is our best option for the moment. */ - pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + timeout_jiffies = jiffies + PCI_DOE_TIMEOUT; + do { + pci_read_config_dword(pdev, offset + PCI_DOE_STATUS, &val); + } while (FIELD_GET(PCI_DOE_STATUS_BUSY, val) && + !time_after(jiffies, timeout_jiffies)); + if (FIELD_GET(PCI_DOE_STATUS_BUSY, val)) return -EBUSY; |