aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Bowling <kbowling@FreeBSD.org>2026-08-15 23:47:10 +0000
committerKevin Bowling <kbowling@FreeBSD.org>2026-08-16 00:01:35 +0000
commit5b48968c1a57bd1a7f086d7e09add59afa158340 (patch)
tree1f5f0557cd101ce4f5f59c54d3217d141c76c2d7
parent3ce28106a887766383c99e5a607396f66ba2e5c1 (diff)
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
-rw-r--r--share/man/man9/pci.915
-rw-r--r--sys/dev/pci/pci.c31
-rw-r--r--sys/dev/pci/pcivar.h1
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
@@ -7079,6 +7079,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.
*
* This function first waits for any pending transactions to complete
@@ -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);