From 52fbf5bdeeef415b28b8e6cdade1e48927927f60 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Tue, 7 Jul 2020 15:46:02 -0700 Subject: [PATCH] PCI: Cache ACS capability offset in device Currently the ACS capability is being looked up at a number of places. Read and store it once at enumeration so that it can be used by all later. No functional change intended. Link: https://lore.kernel.org/r/20200707224604.3737893-2-rajatja@google.com Signed-off-by: Rajat Jain Signed-off-by: Bjorn Helgaas --- drivers/pci/p2pdma.c | 2 +- drivers/pci/pci.c | 20 ++++++++++++++++---- drivers/pci/pci.h | 2 +- drivers/pci/probe.c | 2 +- drivers/pci/quirks.c | 8 ++++---- include/linux/pci.h | 1 + 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index e8e444e..f29a48f 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -253,7 +253,7 @@ static int pci_bridge_has_acs_redir(struct pci_dev *pdev) int pos; u16 ctrl; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); + pos = pdev->acs_cap; if (!pos) return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index eec625f..73a8627 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -831,7 +831,7 @@ static void pci_disable_acs_redir(struct pci_dev *dev) if (!pci_dev_specific_disable_acs_redir(dev)) return; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + pos = dev->acs_cap; if (!pos) { pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n"); return; @@ -857,7 +857,7 @@ static void pci_std_enable_acs(struct pci_dev *dev) u16 cap; u16 ctrl; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + pos = dev->acs_cap; if (!pos) return; @@ -883,7 +883,7 @@ static void pci_std_enable_acs(struct pci_dev *dev) * pci_enable_acs - enable ACS if hardware support it * @dev: the PCI device */ -void pci_enable_acs(struct pci_dev *dev) +static void pci_enable_acs(struct pci_dev *dev) { if (!pci_acs_enable) goto disable_acs_redir; @@ -3362,7 +3362,7 @@ static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) int pos; u16 cap, ctrl; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); + pos = pdev->acs_cap; if (!pos) return false; @@ -3488,6 +3488,18 @@ bool pci_acs_path_enabled(struct pci_dev *start, } /** + * pci_acs_init - Initialize ACS if hardware supports it + * @dev: the PCI device + */ +void pci_acs_init(struct pci_dev *dev) +{ + dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + + if (dev->acs_cap) + pci_enable_acs(dev); +} + +/** * pci_rebar_find_pos - find position of resize ctrl reg for BAR * @pdev: PCI device * @bar: BAR to find diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6d3f758..12fb79f 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -532,7 +532,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, return resource_alignment(res); } -void pci_enable_acs(struct pci_dev *dev); +void pci_acs_init(struct pci_dev *dev); #ifdef CONFIG_PCI_QUIRKS int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); int pci_dev_specific_enable_acs(struct pci_dev *dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2f66988..6d87066 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2390,7 +2390,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_ats_init(dev); /* Address Translation Services */ pci_pri_init(dev); /* Page Request Interface */ pci_pasid_init(dev); /* Process Address Space ID */ - pci_enable_acs(dev); /* Enable ACS P2P upstream forwarding */ + pci_acs_init(dev); /* Access Control Services */ pci_ptm_init(dev); /* Precision Time Measurement */ pci_aer_init(dev); /* Advanced Error Reporting */ pci_dpc_init(dev); /* Downstream Port Containment */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 812bfc3..b341628 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4653,7 +4653,7 @@ static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags) if (!pci_quirk_intel_spt_pch_acs_match(dev)) return -ENOTTY; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + pos = dev->acs_cap; if (!pos) return -ENOTTY; @@ -4961,7 +4961,7 @@ static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev) if (!pci_quirk_intel_spt_pch_acs_match(dev)) return -ENOTTY; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + pos = dev->acs_cap; if (!pos) return -ENOTTY; @@ -4988,7 +4988,7 @@ static int pci_quirk_disable_intel_spt_pch_acs_redir(struct pci_dev *dev) if (!pci_quirk_intel_spt_pch_acs_match(dev)) return -ENOTTY; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); + pos = dev->acs_cap; if (!pos) return -ENOTTY; @@ -5355,7 +5355,7 @@ int pci_idt_bus_quirk(struct pci_bus *bus, int devfn, u32 *l, int timeout) bool found; struct pci_dev *bridge = bus->self; - pos = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ACS); + pos = bridge->acs_cap; /* Disable ACS SV before initial config reads */ if (pos) { diff --git a/include/linux/pci.h b/include/linux/pci.h index c79d833..a26be53 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -486,6 +486,7 @@ struct pci_dev { #ifdef CONFIG_PCI_P2PDMA struct pci_p2pdma *p2pdma; #endif + u16 acs_cap; /* ACS Capability offset */ phys_addr_t rom; /* Physical address if not from BAR */ size_t romlen; /* Length if not from BAR */ char *driver_override; /* Driver name to force a match */ -- 2.7.4