Currently, PCI endpoint drivers (e.g. nvme) use pm_suspend_via_firmware()
to check whether device state is preserved during system suspend. If
firmware will be invoked at the end of suspend, we don't know whether
devices will retain their internal state.
But device context might be lost due to platform issues as well. Having
those checks in endpoint drivers will not scale and will cause a lot of
code duplication.
Add pci_suspend_retains_context() as a sole point of truth that the
endpoint drivers can rely on to check whether they can expect the device
context to be retained or not.
If pci_suspend_retains_context() returns 'false', drivers need to prepare
for context loss by performing actions such as resetting the device, saving
the context, shutting it down etc. If it returns 'true', drivers do not
need to perform any special action and can leave the device in active
state.
Right now, this API only incorporates pm_suspend_via_firmware(), but will
be extended in future commits.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260519-l1ss-fix-v2-1-b2c3a4bdeb15@oss.qualcomm.com
#include <asm/dma.h>
#include <linux/aer.h>
#include <linux/bitfield.h>
+#include <linux/suspend.h>
#include "pci.h"
DEFINE_MUTEX(pci_slot_mutex);
pm_runtime_put_sync(parent);
}
+/**
+ * pci_suspend_retains_context - Check if the platform can retain the device
+ * context during system suspend
+ * @pdev: PCI device to check
+ *
+ * Return: true if the platform can guarantee to retain the device context,
+ * false otherwise.
+ */
+bool pci_suspend_retains_context(struct pci_dev *pdev)
+{
+ /*
+ * If the platform firmware (like ACPI) is involved at the end of
+ * system suspend, device context may not be retained.
+ */
+ if (pm_suspend_via_firmware())
+ return false;
+
+ /* Assume that the context is retained by default */
+ return true;
+}
+EXPORT_SYMBOL_GPL(pci_suspend_retains_context);
+
static const struct dmi_system_id bridge_d3_blacklist[] = {
#ifdef CONFIG_X86
{
pci_select_bars(pdev, IORESOURCE_MEM));
}
+bool pci_suspend_retains_context(struct pci_dev *pdev);
+
#else /* CONFIG_PCI is not enabled */
static inline void pci_set_flags(int flags) { }
static inline void pci_free_irq_vectors(struct pci_dev *dev)
{
}
+
+static inline bool pci_suspend_retains_context(struct pci_dev *pdev)
+{
+ return true;
+}
#endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */