From: Manivannan Sadhasivam Date: Fri, 2 Jan 2026 15:34:48 +0000 (+0530) Subject: PCI: Cache ACS Capabilities register X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f05a5f6745ccc9ff784736608c5a38edb09acc8;p=thirdparty%2Fkernel%2Flinux.git PCI: Cache ACS Capabilities register The ACS Capability register is read-only. Cache it to allow quirks to override it and to avoid re-reading it. Signed-off-by: Manivannan Sadhasivam [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas Tested-by: Marek Szyprowski Tested-by: Naresh Kamboju Link: https://patch.msgid.link/20260102-pci_acs-v3-2-72280b94d288@oss.qualcomm.com --- diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 647c3c4eb4823..e4c11efce34ca 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -893,7 +893,6 @@ static const char *disable_acs_redir_param; static const char *config_acs_param; struct pci_acs { - u16 cap; u16 ctrl; u16 fw_ctrl; }; @@ -996,20 +995,20 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps, static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps) { /* Source Validation */ - caps->ctrl |= (caps->cap & PCI_ACS_SV); + caps->ctrl |= (dev->acs_capabilities & PCI_ACS_SV); /* P2P Request Redirect */ - caps->ctrl |= (caps->cap & PCI_ACS_RR); + caps->ctrl |= (dev->acs_capabilities & PCI_ACS_RR); /* P2P Completion Redirect */ - caps->ctrl |= (caps->cap & PCI_ACS_CR); + caps->ctrl |= (dev->acs_capabilities & PCI_ACS_CR); /* Upstream Forwarding */ - caps->ctrl |= (caps->cap & PCI_ACS_UF); + caps->ctrl |= (dev->acs_capabilities & PCI_ACS_UF); /* Enable Translation Blocking for external devices and noats */ if (pci_ats_disabled() || dev->external_facing || dev->untrusted) - caps->ctrl |= (caps->cap & PCI_ACS_TB); + caps->ctrl |= (dev->acs_capabilities & PCI_ACS_TB); } /** @@ -1032,7 +1031,6 @@ void pci_enable_acs(struct pci_dev *dev) if (!pos) return; - pci_read_config_word(dev, pos + PCI_ACS_CAP, &caps.cap); pci_read_config_word(dev, pos + PCI_ACS_CTRL, &caps.ctrl); caps.fw_ctrl = caps.ctrl; @@ -3515,7 +3513,7 @@ void pci_configure_ari(struct pci_dev *dev) static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) { int pos; - u16 cap, ctrl; + u16 ctrl; pos = pdev->acs_cap; if (!pos) @@ -3526,8 +3524,7 @@ static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) * or only required if controllable. Features missing from the * capability field can therefore be assumed as hard-wired enabled. */ - pci_read_config_word(pdev, pos + PCI_ACS_CAP, &cap); - acs_flags &= (cap | PCI_ACS_EC); + acs_flags &= (pdev->acs_capabilities | PCI_ACS_EC); pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); return (ctrl & acs_flags) == acs_flags; @@ -3648,7 +3645,14 @@ bool pci_acs_path_enabled(struct pci_dev *start, */ void pci_acs_init(struct pci_dev *dev) { + int pos; + dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + pos = dev->acs_cap; + if (!pos) + return; + + pci_read_config_word(dev, pos + PCI_ACS_CAP, &dev->acs_capabilities); } /** diff --git a/include/linux/pci.h b/include/linux/pci.h index 864775651c6fa..6195e040b29c6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -558,6 +558,7 @@ struct pci_dev { struct pci_tsm *tsm; /* TSM operation state */ #endif u16 acs_cap; /* ACS Capability offset */ + u16 acs_capabilities; /* ACS Capabilities */ u8 supported_speeds; /* Supported Link Speeds Vector */ phys_addr_t rom; /* Physical address if not from BAR */ size_t romlen; /* Length if not from BAR */