summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2024-11-25 13:40:43 -0600
committerBjorn Helgaas <bhelgaas@google.com>2024-11-25 13:40:43 -0600
commit73bdd7304a0120cf6e6fa3d20cf9e5ef7823f51f (patch)
tree91f694df71f00472af8607fa8124ecc0b94c627a /drivers
parentd957ff7acaf27674e73db716a2dc0ae8170144cd (diff)
parent86efc62d031307e53ad4011e0aa8898e029cef47 (diff)
downloadlwn-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.c14
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;