git: 5b48968c1a57 - main - pci: Export pcie_flr_supported()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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);