summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.h
diff options
context:
space:
mode:
authorHans Zhang <18255117159@163.com>2025-08-13 22:45:25 +0800
committerBjorn Helgaas <bhelgaas@google.com>2025-08-14 15:03:40 -0500
commit3c02084d8fa521192ea19722b1e5efae8096d939 (patch)
treeec90c776695c374992f828d95f8b6d42997c80ba /drivers/pci/pci.h
parent37d1ade89606875c9cd6eb3b4ee416b7e1800fc4 (diff)
PCI: Refactor capability search into PCI_FIND_NEXT_CAP()
The PCI Capability search functionality is duplicated across the PCI core and several controller drivers. The core's current implementation requires fully initialized PCI device and bus structures, which prevents controller drivers from using it during early initialization phases before these structures are available. Move the Capability search logic into a PCI_FIND_NEXT_CAP() macro that accepts a config space accessor function as an argument. This enables controller drivers to perform Capability discovery using their early access mechanisms prior to full device initialization while sharing the Capability search code. Convert the existing PCI core Capability search implementation to use PCI_FIND_NEXT_CAP(). Controller drivers can later use this with their early access mechanisms while maintaining the existing protection against infinite loops through preserved TTL checks. Signed-off-by: Hans Zhang <18255117159@163.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: Niklas Schnelle <schnelle@linux.ibm.com> Link: https://patch.msgid.link/20250813144529.303548-3-18255117159@163.com
Diffstat (limited to 'drivers/pci/pci.h')
-rw-r--r--drivers/pci/pci.h45
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 34f65d69662e..81580987509f 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -2,6 +2,8 @@
#ifndef DRIVERS_PCI_H
#define DRIVERS_PCI_H
+#include <linux/align.h>
+#include <linux/bitfield.h>
#include <linux/pci.h>
struct pcie_tlp_log;
@@ -88,6 +90,49 @@ bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
bool pcie_cap_has_lnkctl2(const struct pci_dev *dev);
bool pcie_cap_has_rtctl(const struct pci_dev *dev);
+/* Standard Capability finder */
+/**
+ * PCI_FIND_NEXT_CAP - Find a PCI standard capability
+ * @read_cfg: Function pointer for reading PCI config space
+ * @start: Starting position to begin search
+ * @cap: Capability ID to find
+ * @args: Arguments to pass to read_cfg function
+ *
+ * Search the capability list in PCI config space to find @cap.
+ * Implements TTL (time-to-live) protection against infinite loops.
+ *
+ * Return: Position of the capability if found, 0 otherwise.
+ */
+#define PCI_FIND_NEXT_CAP(read_cfg, start, cap, args...) \
+({ \
+ int __ttl = PCI_FIND_CAP_TTL; \
+ u8 __id, __found_pos = 0; \
+ u8 __pos = (start); \
+ u16 __ent; \
+ \
+ read_cfg##_byte(args, __pos, &__pos); \
+ \
+ while (__ttl--) { \
+ if (__pos < PCI_STD_HEADER_SIZEOF) \
+ break; \
+ \
+ __pos = ALIGN_DOWN(__pos, 4); \
+ read_cfg##_word(args, __pos, &__ent); \
+ \
+ __id = FIELD_GET(PCI_CAP_ID_MASK, __ent); \
+ if (__id == 0xff) \
+ break; \
+ \
+ if (__id == (cap)) { \
+ __found_pos = __pos; \
+ break; \
+ } \
+ \
+ __pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, __ent); \
+ } \
+ __found_pos; \
+})
+
/* Functions internal to the PCI core code */
#ifdef CONFIG_DMI