Page MenuHomeFreeBSD

D59477.id186119.diff
No OneTemporary

D59477.id186119.diff

Index: share/man/man9/Makefile
===================================================================
--- share/man/man9/Makefile
+++ share/man/man9/Makefile
@@ -1823,8 +1823,10 @@
pci.9 pci_disable_busmaster.9 \
pci.9 pci_disable_io.9 \
pci.9 pci_enable_busmaster.9 \
+ pci.9 pci_enable_busmaster_checked.9 \
pci.9 pci_enable_io.9 \
pci.9 pci_enable_pme.9 \
+ pci.9 pci_fence_dma.9 \
pci.9 pci_find_bsf.9 \
pci.9 pci_find_cap.9 \
pci.9 pci_find_dbsf.9 \
Index: share/man/man9/pci.9
===================================================================
--- share/man/man9/pci.9
+++ 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 30, 2026
+.Dd September 7, 2026
.Dt PCI 9
.Os
.Sh NAME
@@ -35,8 +35,10 @@
.Nm pci_disable_busmaster ,
.Nm pci_disable_io ,
.Nm pci_enable_busmaster ,
+.Nm pci_enable_busmaster_checked ,
.Nm pci_enable_io ,
.Nm pci_enable_pme ,
+.Nm pci_fence_dma ,
.Nm pci_find_bsf ,
.Nm pci_find_cap ,
.Nm pci_find_dbsf ,
@@ -98,9 +100,13 @@
.Ft int
.Fn pci_enable_busmaster "device_t dev"
.Ft int
+.Fn pci_enable_busmaster_checked "device_t dev"
+.Ft int
.Fn pci_enable_io "device_t dev" "int space"
.Ft void
.Fn pci_enable_pme "device_t dev"
+.Ft int
+.Fn pci_fence_dma "device_t dev"
.Ft device_t
.Fn pci_find_bsf "uint8_t bus" "uint8_t slot" "uint8_t func"
.Ft int
@@ -608,6 +614,35 @@
function clears this bit.
.Pp
The
+.Fn pci_enable_busmaster_checked
+function enables PCI bus mastering and verifies that the bus master enable bit
+is set.
+It returns
+.Er ENXIO
+if PCI configuration space is inaccessible,
+.Er EIO
+if the bit remains clear, or an error returned by
+.Fn pci_enable_busmaster .
+.Pp
+The
+.Fn pci_fence_dma
+function disables PCI bus mastering, verifies that the bus master enable bit
+is clear, and waits for pending PCI-express transactions to drain.
+It waits for at least 10 milliseconds and otherwise uses the maximum
+completion timeout configured for
+.Fa dev .
+The function may sleep.
+The function returns zero when DMA is fenced and otherwise returns
+.Er ENXIO
+if PCI configuration space becomes inaccessible,
+.Er EIO
+or an error returned by
+.Fn pci_disable_busmaster
+if bus mastering remains enabled, and
+.Er ETIMEDOUT
+if a present PCI-express function retains pending transactions.
+.Pp
+The
.Fn pci_enable_io
function enables memory or I/O port address decoding for the device
.Fa dev ,
Index: sys/dev/pci/pci.c
===================================================================
--- sys/dev/pci/pci.c
+++ sys/dev/pci/pci.c
@@ -7061,6 +7061,61 @@
}
}
+/* Enable bus mastering and verify the command-register write. */
+int
+pci_enable_busmaster_checked(device_t dev)
+{
+ uint16_t command;
+ int error;
+
+ command = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (command == 0xffff)
+ return (ENXIO);
+ if ((command & PCIM_CMD_BUSMASTEREN) != 0)
+ return (0);
+
+ error = pci_enable_busmaster(dev);
+ command = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (command == 0xffff)
+ return (ENXIO);
+ if ((command & PCIM_CMD_BUSMASTEREN) == 0)
+ return (error != 0 ? error : EIO);
+ return (0);
+}
+
+/*
+ * Disable bus mastering and wait for transactions initiated before the
+ * command-register write to drain.
+ *
+ * Returns zero once DMA is fenced, ENXIO if PCI configuration space becomes
+ * inaccessible, EIO or a bus-method error if bus mastering remains enabled,
+ * or ETIMEDOUT if a present PCI-express function retains pending
+ * transactions. This function may sleep.
+ */
+int
+pci_fence_dma(device_t dev)
+{
+ u_int timeout;
+ uint16_t command;
+ int error;
+
+ error = pci_disable_busmaster(dev);
+ command = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (command == 0xffff)
+ return (ENXIO);
+ if ((command & PCIM_CMD_BUSMASTEREN) != 0)
+ return (error != 0 ? error : EIO);
+
+ timeout = max(pcie_get_max_completion_timeout(dev) / 1000, 10);
+ if (pcie_wait_for_pending_transactions(dev, timeout))
+ return (0);
+
+ /* Report a function which disappeared during the wait separately. */
+ if (pci_read_config(dev, PCIR_COMMAND, 2) == 0xffff)
+ return (ENXIO);
+ return (ETIMEDOUT);
+}
+
void
pcie_apei_error(device_t dev, int sev, uint8_t *aerp)
{
Index: sys/dev/pci/pcivar.h
===================================================================
--- sys/dev/pci/pcivar.h
+++ sys/dev/pci/pcivar.h
@@ -698,6 +698,8 @@
int pci_get_relaxed_ordering_enabled(device_t dev);
int pci_get_max_payload(device_t dev);
int pci_get_max_read_req(device_t dev);
+int pci_enable_busmaster_checked(device_t dev);
+int pci_fence_dma(device_t dev);
void pci_restore_state(device_t dev);
void pci_save_state(device_t dev);
int pci_set_max_read_req(device_t dev, int size);

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 12, 3:54 PM (14 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38801626
Default Alt Text
D59477.id186119.diff (4 KB)

Event Timeline