Date: Fri, 07 Aug 2026 04:31:12 +0000 From: Kevin Bowling <kbowling@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: a9752e9ac8a6 - main - pci: Preserve adjusted PCIe control state Message-ID: <6a755f90.2698a.4e64aa79@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=a9752e9ac8a635f49ca058dd7268298840c7e915 commit a9752e9ac8a635f49ca058dd7268298840c7e915 Author: Kevin Bowling <kbowling@FreeBSD.org> AuthorDate: 2026-08-06 09:36:43 +0000 Commit: Kevin Bowling <kbowling@FreeBSD.org> CommitDate: 2026-08-07 04:30:50 +0000 pci: Preserve adjusted PCIe control state The PCI bus changes live capability registers after the initial configuration snapshot has been saved. A later driver reprobe restores that snapshot and can silently undo the adjustment. Update the cached Device Control and Root Control bits together with pcie_adjust_config() writes. Route the persistent Maximum Read Request setter and the bus-owned AER control changes through that helper as well, so they share the same restore semantics as MPS reconciliation. Document the persistent-write contract. Merge only explicitly adjusted bits into the saved image so unrelated or transient bits observed during the hardware read-modify-write cannot become persistent. MFC after: 2 weeks --- share/man/man9/pci.9 | 11 ++++++++++- sys/dev/pci/pci.c | 41 +++++++++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/share/man/man9/pci.9 b/share/man/man9/pci.9 index 4d69d3a4240f..c94982f5f218 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 May 18, 2026 +.Dd August 6, 2026 .Dt PCI 9 .Os .Sh NAME @@ -253,6 +253,15 @@ to the value in Any bits not specified in .Fa mask are preserved. +For 16-bit accesses to +.Dv PCIER_DEVICE_CTL +or +.Dv PCIER_ROOT_CTL , +the corresponding bits in the saved PCI configuration state are also updated +so the adjustment persists across configuration restores. +Use +.Fn pcie_write_config +for transient changes that must not be saved. The previous value of the register is returned. .Pp The diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index b690c3412356..95b8e831e743 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -2312,10 +2312,9 @@ pci_set_max_read_req(device_t dev, int size) if (size > 4096) size = 4096; size = (1 << (fls(size) - 1)); - val = pci_read_config(dev, cap + PCIER_DEVICE_CTL, 2); - val &= ~PCIEM_CTL_MAX_READ_REQUEST; - val |= (fls(size) - 8) << 12; - pci_write_config(dev, cap + PCIER_DEVICE_CTL, val, 2); + val = (fls(size) - 8) << 12; + pcie_adjust_config(dev, PCIER_DEVICE_CTL, + PCIEM_CTL_MAX_READ_REQUEST, val, 2); return (size); } @@ -2359,6 +2358,7 @@ pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value, int width) { struct pci_devinfo *dinfo = device_get_ivars(dev); + uint16_t *saved; uint32_t old, new; int cap; @@ -2373,6 +2373,22 @@ pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value, new = old & ~mask; new |= (value & mask); pci_write_config(dev, cap + reg, new, width); + /* Apply only the requested policy bits to the saved restore image. */ + if (width == 2) { + saved = NULL; + switch (reg) { + case PCIER_DEVICE_CTL: + saved = &dinfo->cfg.pcie.pcie_device_ctl; + break; + case PCIER_ROOT_CTL: + saved = &dinfo->cfg.pcie.pcie_root_ctl; + break; + } + if (saved != NULL) { + *saved &= ~(uint16_t)mask; + *saved |= (uint16_t)(value & mask); + } + } return (old); } @@ -4461,16 +4477,12 @@ pci_add_child_clear_aer(device_t dev, struct pci_devinfo *dinfo) { int aer; uint32_t r; - uint16_t r2; if (dinfo->cfg.pcie.pcie_location != 0 && dinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT) { - r2 = pci_read_config(dev, dinfo->cfg.pcie.pcie_location + - PCIER_ROOT_CTL, 2); - r2 &= ~(PCIEM_ROOT_CTL_SERR_CORR | - PCIEM_ROOT_CTL_SERR_NONFATAL | PCIEM_ROOT_CTL_SERR_FATAL); - pci_write_config(dev, dinfo->cfg.pcie.pcie_location + - PCIER_ROOT_CTL, r2, 2); + r = PCIEM_ROOT_CTL_SERR_CORR | + PCIEM_ROOT_CTL_SERR_NONFATAL | PCIEM_ROOT_CTL_SERR_FATAL; + pcie_adjust_config(dev, PCIER_ROOT_CTL, r, 0, 2); } if (pci_find_extcap(dev, PCIZ_AER, &aer) == 0) { r = pci_read_config(dev, aer + PCIR_AER_UC_STATUS, 4); @@ -4522,12 +4534,9 @@ pci_add_child_clear_aer(device_t dev, struct pci_devinfo *dinfo) PCIM_AER_COR_HEADER_LOG_OVFLOW); pci_write_config(dev, aer + PCIR_AER_COR_MASK, r, 4); - r = pci_read_config(dev, dinfo->cfg.pcie.pcie_location + - PCIER_DEVICE_CTL, 2); - r |= PCIEM_CTL_COR_ENABLE | PCIEM_CTL_NFER_ENABLE | + r = PCIEM_CTL_COR_ENABLE | PCIEM_CTL_NFER_ENABLE | PCIEM_CTL_FER_ENABLE | PCIEM_CTL_URR_ENABLE; - pci_write_config(dev, dinfo->cfg.pcie.pcie_location + - PCIER_DEVICE_CTL, r, 2); + pcie_adjust_config(dev, PCIER_DEVICE_CTL, r, r, 2); } }home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a755f90.2698a.4e64aa79>
