From: Abhin Parekadan Jose <abhinjoses@gmail.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
Lukas Wunner <lukas@wunner.de>,
"Michael S. Tsirkin" <mst@redhat.com>
Cc: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Shuai Xue" <xueshuai@linux.alibaba.com>,
"Kees Cook" <kees@kernel.org>,
"Mahesh J Salgaonkar" <mahesh@linux.ibm.com>,
"Oliver O'Halloran" <oohall@gmail.com>,
linux-pci@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-kernel@vger.kernel.org,
"Abhin Parekadan Jose" <abhinjoses@gmail.com>
Subject: [PATCH RFC v3 3/5] PCI/DPC: Add pci_dpc_wait_recovery()
Date: Sun, 27 Sep 2026 17:52:00 +0000 [thread overview]
Message-ID: <20260927175203.928270-4-abhinjoses@gmail.com> (raw)
In-Reply-To: <20260927175203.928270-1-abhinjoses@gmail.com>
pci_dpc_recovered() awaits completion of DPC recovery and then tells
whether DPC recovered successfully, using test_and_clear_bit() on
PCI_DPC_RECOVERED. The answer is one-shot: only the first caller sees
true.
Split pci_dpc_recovered() into:
- pci_dpc_hp_sync_supported(), the check whether hotplug can
synchronize with DPC at all.
- dpc_wait_completed(), the wait for recovery with its 4 second
timeout;
- the final test_and_clear_bit().
Add pci_dpc_wait_recovery(), which does the check and the wait but
leaves PCI_DPC_RECOVERED alone. No functional change intended.
Signed-off-by: Abhin Parekadan Jose <abhinjoses@gmail.com>
Assisted-by: LLM
---
drivers/pci/pci.h | 2 ++
drivers/pci/pcie/dpc.c | 54 ++++++++++++++++++++++++++++++++----------
2 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index cfa0202bf610b..b1d9df904c625 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -941,12 +941,14 @@ void pci_restore_dpc_state(struct pci_dev *dev);
void pci_dpc_init(struct pci_dev *pdev);
void dpc_process_error(struct pci_dev *pdev);
pci_ers_result_t dpc_reset_link(struct pci_dev *pdev);
+void pci_dpc_wait_recovery(struct pci_dev *pdev);
bool pci_dpc_recovered(struct pci_dev *pdev);
unsigned int dpc_tlp_log_len(struct pci_dev *dev);
#else
static inline void pci_save_dpc_state(struct pci_dev *dev) { }
static inline void pci_restore_dpc_state(struct pci_dev *dev) { }
static inline void pci_dpc_init(struct pci_dev *pdev) { }
+static inline void pci_dpc_wait_recovery(struct pci_dev *pdev) { }
static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; }
#endif
diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
index 2b779bd1d861b..a6438a7e3d9c7 100644
--- a/drivers/pci/pcie/dpc.c
+++ b/drivers/pci/pcie/dpc.c
@@ -92,15 +92,7 @@ static bool dpc_completed(struct pci_dev *pdev)
return true;
}
-/**
- * pci_dpc_recovered - whether DPC triggered and has recovered successfully
- * @pdev: PCI device
- *
- * Return true if DPC was triggered for @pdev and has recovered successfully.
- * Wait for recovery if it hasn't completed yet. Called from the PCIe hotplug
- * driver to recognize and ignore Link Down/Up events caused by DPC.
- */
-bool pci_dpc_recovered(struct pci_dev *pdev)
+static bool pci_dpc_hp_sync_supported(struct pci_dev *pdev)
{
struct pci_host_bridge *host;
@@ -108,13 +100,18 @@ bool pci_dpc_recovered(struct pci_dev *pdev)
return false;
/*
- * Synchronization between hotplug and DPC is not supported
- * if DPC is owned by firmware and EDR is not enabled.
- */
+ * Synchronization between hotplug and DPC is only supported if DPC is owned
+ * by the OS, or by firmware with EDR enabled.
+ */
host = pci_find_host_bridge(pdev->bus);
if (!host->native_dpc && !IS_ENABLED(CONFIG_PCIE_EDR))
return false;
+ return true;
+}
+
+static void dpc_wait_completed(struct pci_dev *pdev)
+{
/*
* Need a timeout in case DPC never completes due to failure of
* dpc_wait_rp_inactive(). The spec doesn't mandate a time limit,
@@ -122,6 +119,39 @@ bool pci_dpc_recovered(struct pci_dev *pdev)
*/
wait_event_timeout(dpc_completed_waitqueue, dpc_completed(pdev),
msecs_to_jiffies(4000));
+}
+
+/**
+ * pci_dpc_wait_recovery - await completion of DPC recovery
+ * @pdev: PCI device
+ *
+ * Wait for recovery if DPC was triggered for @pdev and recovery hasn't
+ * completed yet. Unlike pci_dpc_recovered(), leave the record of a
+ * successful recovery in place. Called from the PCIe hotplug driver where
+ * it needs the link to have settled, but not the cause of a link change.
+ * Nothing is awaited if synchronization between hotplug and DPC is not
+ * supported for @pdev.
+ */
+void pci_dpc_wait_recovery(struct pci_dev *pdev)
+{
+ if (pci_dpc_hp_sync_supported(pdev))
+ dpc_wait_completed(pdev);
+}
+
+/**
+ * pci_dpc_recovered - whether DPC triggered and has recovered successfully
+ * @pdev: PCI device
+ *
+ * Return true if DPC was triggered for @pdev and has recovered successfully.
+ * Wait for recovery if it hasn't completed yet. Called from the PCIe hotplug
+ * driver to recognize and ignore Link Down/Up events caused by DPC.
+ */
+bool pci_dpc_recovered(struct pci_dev *pdev)
+{
+ if (!pci_dpc_hp_sync_supported(pdev))
+ return false;
+
+ dpc_wait_completed(pdev);
return test_and_clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags);
}
--
2.51.1
next prev parent reply other threads:[~2026-09-27 17:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-27 17:51 [PATCH RFC v3 0/5] PCI: pciehp: Report surprise removal during safe removal Abhin Parekadan Jose
2026-09-27 17:51 ` [PATCH RFC v3 1/5] PCI: Report surprise removal event Abhin Parekadan Jose
2026-09-27 18:02 ` sashiko-bot
2026-09-27 17:51 ` [PATCH RFC v3 2/5] PCI: pciehp: Add pci_hp_wait_link_change() Abhin Parekadan Jose
2026-09-27 17:56 ` sashiko-bot
2026-09-27 17:52 ` Abhin Parekadan Jose [this message]
2026-09-27 17:55 ` [PATCH RFC v3 3/5] PCI/DPC: Add pci_dpc_wait_recovery() sashiko-bot
2026-09-27 17:52 ` [PATCH RFC v3 4/5] PCI: pciehp: Report surprise removal from pciehp_isr() Abhin Parekadan Jose
2026-09-27 17:59 ` sashiko-bot
2026-09-27 17:52 ` [PATCH RFC v3 5/5] misc: Add edu_srpoc surprise removal POC driver Abhin Parekadan Jose
2026-09-27 17:59 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260927175203.928270-4-abhinjoses@gmail.com \
--to=abhinjoses@gmail.com \
--cc=bhelgaas@google.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=lukas@wunner.de \
--cc=mahesh@linux.ibm.com \
--cc=mst@redhat.com \
--cc=oohall@gmail.com \
--cc=xueshuai@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.