git: 5b48968c1a57 - main - pci: Export pcie_flr_supported()

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Sun, 16 Aug 2026 00:02:29 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=5b48968c1a57bd1a7f086d7e09add59afa158340

commit 5b48968c1a57bd1a7f086d7e09add59afa158340
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-15 23:47:10 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-16 00:01:35 +0000

    pci: Export pcie_flr_supported()
    
    Move the capability and quirk checks used by pcie_flr() into a public
    side effect free helper.  This lets callers determine whether an FLR
    can be attempted before quiescing a device or saving state.
    
    The helper considers the advertised PCIe FLR capability and both the
    enable and disable FLR quirks.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
---
 share/man/man9/pci.9 | 15 ++++++++++++++-
 sys/dev/pci/pci.c    | 31 ++++++++++++++++++++++++-------
 sys/dev/pci/pcivar.h |  1 +
 3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/share/man/man9/pci.9 b/share/man/man9/pci.9
index c94982f5f218..65d1f0bc867b 100644
--- a/share/man/man9/pci.9
+++ b/share/man/man9/pci.9
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 6, 2026
+.Dd August 15, 2026
 .Dt PCI 9
 .Os
 .Sh NAME
@@ -72,6 +72,7 @@
 .Nm pci_write_config ,
 .Nm pcie_adjust_config ,
 .Nm pcie_flr ,
+.Nm pcie_flr_supported ,
 .Nm pcie_get_max_completion_timeout ,
 .Nm pcie_read_config ,
 .Nm pcie_wait_for_pending_transactions ,
@@ -169,6 +170,8 @@
 .Fc
 .Ft bool
 .Fn pcie_flr "device_t dev" "u_int max_delay" "bool force"
+.Ft bool
+.Fn pcie_flr_supported "device_t dev"
 .Ft int
 .Fn pcie_get_max_completion_timeout "device_t dev"
 .Ft uint32_t
@@ -863,6 +866,16 @@ Note that
 .Nm pcie_flr
 does not save and restore any state around the reset.
 The caller should save and restore state as needed.
+.Pp
+The
+.Fn pcie_flr_supported
+function returns
+.Dv true
+if
+.Fa dev
+supports FLR according to its PCI-express capability and the PCI quirk
+policy.
+It does not alter the device.
 .Ss Message Signaled Interrupts
 Message Signaled Interrupts
 .Pq MSI
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 34ee261604a2..430eca38c0b9 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -7078,6 +7078,28 @@ pcie_apei_error(device_t dev, int sev, uint8_t *aerp)
 	}
 }
 
+/*
+ * Return true if the device supports FLR, taking both its advertised
+ * capability and the PCI quirk policy into account.
+ */
+bool
+pcie_flr_supported(device_t dev)
+{
+	struct pci_devinfo *dinfo = device_get_ivars(dev);
+	int cap;
+
+	cap = dinfo->cfg.pcie.pcie_location;
+	if (cap == 0)
+		return (false);
+
+	if (!(pci_read_config(dev, cap + PCIER_DEVICE_CAP, 4) & PCIEM_CAP_FLR) &&
+	    !pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_ENABLE_FLR))
+		return (false);
+	if (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_FLR))
+		return (false);
+	return (true);
+}
+
 /*
  * Perform a Function Level Reset (FLR) on a device.
  *
@@ -7102,15 +7124,10 @@ pcie_flr(device_t dev, u_int max_delay, bool force)
 	int compl_delay;
 	int cap;
 
-	cap = dinfo->cfg.pcie.pcie_location;
-	if (cap == 0)
+	if (!pcie_flr_supported(dev))
 		return (false);
 
-	if (!(pci_read_config(dev, cap + PCIER_DEVICE_CAP, 4) & PCIEM_CAP_FLR) &&
-	    !pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_ENABLE_FLR))
-		return (false);
-	if (pci_has_quirk(pci_get_devid(dev), PCI_QUIRK_DISABLE_FLR))
-		return (false);
+	cap = dinfo->cfg.pcie.pcie_location;
 
 	/*
 	 * Disable busmastering to prevent generation of new
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 27bac22c7896..19ba20a7d1f3 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -711,6 +711,7 @@ uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask,
 	    uint32_t value, int width);
 void	pcie_apei_error(device_t dev, int sev, uint8_t *aer);
 bool	pcie_flr(device_t dev, u_int max_delay, bool force);
+bool	pcie_flr_supported(device_t dev);
 int	pcie_get_max_completion_timeout(device_t dev);
 bool	pcie_wait_for_pending_transactions(device_t dev, u_int max_delay);
 int	pcie_link_reset(device_t port, int pcie_location);