summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQiang Yu <qiang.yu@oss.qualcomm.com>2025-11-10 09:59:40 +0300
committerManivannan Sadhasivam <mani@kernel.org>2025-12-18 10:16:16 +0300
commita2582e05e39adf9ab82a02561cd6f70738540ae0 (patch)
tree2e7f355a4ccac7310431c2913e1bf60f95277fae
parent8f0b4cce4481fb22653697cced8d0d04027cb1e8 (diff)
downloadlinux-a2582e05e39adf9ab82a02561cd6f70738540ae0.tar.xz
PCI: Add preceding capability position support in PCI_FIND_NEXT_*_CAP macros
Add support for finding the preceding capability position in PCI capability list by extending the capability finding macros with an additional parameter. This functionality is essential for modifying PCI capability list, as it provides the necessary information to update the "next" pointer of the predecessor capability when removing entries. Modify two macros to accept a new 'prev_ptr' parameter: - PCI_FIND_NEXT_CAP - Now accepts 'prev_ptr' parameter for standard capabilities - PCI_FIND_NEXT_EXT_CAP - Now accepts 'prev_ptr' parameter for extended capabilities When a capability is found, these macros: - Store the position of the preceding capability in *prev_ptr (if prev_ptr != NULL) - Maintain all existing functionality when prev_ptr is NULL Update current callers to accommodate this API change by passing NULL to 'prev_ptr' argument if they do not care about the preceding capability position. No functional changes to driver behavior result from this commit as it maintains the existing capability finding functionality while adding the infrastructure for future capability removal operations. Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com> Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Link: https://patch.msgid.link/20251109-remove_cap-v1-1-2208f46f4dc2@oss.qualcomm.com
-rw-r--r--drivers/pci/controller/cadence/pcie-cadence.c4
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c2
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c6
-rw-r--r--drivers/pci/pci.c8
-rw-r--r--drivers/pci/pci.h23
5 files changed, 29 insertions, 14 deletions
diff --git a/drivers/pci/controller/cadence/pcie-cadence.c b/drivers/pci/controller/cadence/pcie-cadence.c
index e6f1a4ac0fb7..a1eada56edba 100644
--- a/drivers/pci/controller/cadence/pcie-cadence.c
+++ b/drivers/pci/controller/cadence/pcie-cadence.c
@@ -13,13 +13,13 @@
u8 cdns_pcie_find_capability(struct cdns_pcie *pcie, u8 cap)
{
return PCI_FIND_NEXT_CAP(cdns_pcie_read_cfg, PCI_CAPABILITY_LIST,
- cap, pcie);
+ cap, NULL, pcie);
}
EXPORT_SYMBOL_GPL(cdns_pcie_find_capability);
u16 cdns_pcie_find_ext_capability(struct cdns_pcie *pcie, u8 cap)
{
- return PCI_FIND_NEXT_EXT_CAP(cdns_pcie_read_cfg, 0, cap, pcie);
+ return PCI_FIND_NEXT_EXT_CAP(cdns_pcie_read_cfg, 0, cap, NULL, pcie);
}
EXPORT_SYMBOL_GPL(cdns_pcie_find_ext_capability);
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 19571ac2b961..f6c54625486e 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(dw_pcie_ep_reset_bar);
static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap)
{
return PCI_FIND_NEXT_CAP(dw_pcie_ep_read_cfg, PCI_CAPABILITY_LIST,
- cap, ep, func_no);
+ cap, NULL, ep, func_no);
}
/**
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 75fc8b767fcc..5d7a7e6f5724 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -226,13 +226,13 @@ void dw_pcie_version_detect(struct dw_pcie *pci)
u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap)
{
return PCI_FIND_NEXT_CAP(dw_pcie_read_cfg, PCI_CAPABILITY_LIST, cap,
- pci);
+ NULL, pci);
}
EXPORT_SYMBOL_GPL(dw_pcie_find_capability);
u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
{
- return PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, 0, cap, pci);
+ return PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, 0, cap, NULL, pci);
}
EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);
@@ -246,7 +246,7 @@ static u16 __dw_pcie_find_vsec_capability(struct dw_pcie *pci, u16 vendor_id,
return 0;
while ((vsec = PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, vsec,
- PCI_EXT_CAP_ID_VNDR, pci))) {
+ PCI_EXT_CAP_ID_VNDR, NULL, pci))) {
header = dw_pcie_readl_dbi(pci, vsec + PCI_VNDR_HEADER);
if (PCI_VNDR_HEADER_ID(header) == vsec_id)
return vsec;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 13dbb405dc31..b1142fbbd6e5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -426,7 +426,7 @@ found:
static u8 __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap)
{
- return PCI_FIND_NEXT_CAP(pci_bus_read_config, pos, cap, bus, devfn);
+ return PCI_FIND_NEXT_CAP(pci_bus_read_config, pos, cap, NULL, bus, devfn);
}
u8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
@@ -531,7 +531,7 @@ u16 pci_find_next_ext_capability(struct pci_dev *dev, u16 start, int cap)
return 0;
return PCI_FIND_NEXT_EXT_CAP(pci_bus_read_config, start, cap,
- dev->bus, dev->devfn);
+ NULL, dev->bus, dev->devfn);
}
EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
@@ -600,7 +600,7 @@ static u8 __pci_find_next_ht_cap(struct pci_dev *dev, u8 pos, int ht_cap)
mask = HT_5BIT_CAP_MASK;
pos = PCI_FIND_NEXT_CAP(pci_bus_read_config, pos,
- PCI_CAP_ID_HT, dev->bus, dev->devfn);
+ PCI_CAP_ID_HT, NULL, dev->bus, dev->devfn);
while (pos) {
rc = pci_read_config_byte(dev, pos + 3, &cap);
if (rc != PCIBIOS_SUCCESSFUL)
@@ -611,7 +611,7 @@ static u8 __pci_find_next_ht_cap(struct pci_dev *dev, u8 pos, int ht_cap)
pos = PCI_FIND_NEXT_CAP(pci_bus_read_config,
pos + PCI_CAP_LIST_NEXT,
- PCI_CAP_ID_HT, dev->bus,
+ PCI_CAP_ID_HT, NULL, dev->bus,
dev->devfn);
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 0e67014aa001..1d1742bd6a1b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -103,17 +103,21 @@ bool pcie_cap_has_rtctl(const struct pci_dev *dev);
* @read_cfg: Function pointer for reading PCI config space
* @start: Starting position to begin search
* @cap: Capability ID to find
+ * @prev_ptr: Pointer to store position of preceding capability (optional)
* @args: Arguments to pass to read_cfg function
*
- * Search the capability list in PCI config space to find @cap.
+ * Search the capability list in PCI config space to find @cap. If
+ * found, update *prev_ptr with the position of the preceding capability
+ * (if prev_ptr != NULL)
* 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...) \
+#define PCI_FIND_NEXT_CAP(read_cfg, start, cap, prev_ptr, args...) \
({ \
int __ttl = PCI_FIND_CAP_TTL; \
- u8 __id, __found_pos = 0; \
+ u8 __id, __found_pos = 0; \
+ u8 __prev_pos = (start); \
u8 __pos = (start); \
u16 __ent; \
\
@@ -132,9 +136,12 @@ bool pcie_cap_has_rtctl(const struct pci_dev *dev);
\
if (__id == (cap)) { \
__found_pos = __pos; \
+ if (prev_ptr != NULL) \
+ *(u8 *)prev_ptr = __prev_pos; \
break; \
} \
\
+ __prev_pos = __pos; \
__pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, __ent); \
} \
__found_pos; \
@@ -146,21 +153,26 @@ bool pcie_cap_has_rtctl(const struct pci_dev *dev);
* @read_cfg: Function pointer for reading PCI config space
* @start: Starting position to begin search (0 for initial search)
* @cap: Extended capability ID to find
+ * @prev_ptr: Pointer to store position of preceding capability (optional)
* @args: Arguments to pass to read_cfg function
*
* Search the extended capability list in PCI config space to find @cap.
+ * If found, update *prev_ptr with the position of the preceding capability
+ * (if prev_ptr != NULL)
* Implements TTL protection against infinite loops using a calculated
* maximum search count.
*
* Return: Position of the capability if found, 0 otherwise.
*/
-#define PCI_FIND_NEXT_EXT_CAP(read_cfg, start, cap, args...) \
+#define PCI_FIND_NEXT_EXT_CAP(read_cfg, start, cap, prev_ptr, args...) \
({ \
u16 __pos = (start) ?: PCI_CFG_SPACE_SIZE; \
u16 __found_pos = 0; \
+ u16 __prev_pos; \
int __ttl, __ret; \
u32 __header; \
\
+ __prev_pos = __pos; \
__ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; \
while (__ttl-- > 0 && __pos >= PCI_CFG_SPACE_SIZE) { \
__ret = read_cfg##_dword(args, __pos, &__header); \
@@ -172,9 +184,12 @@ bool pcie_cap_has_rtctl(const struct pci_dev *dev);
\
if (PCI_EXT_CAP_ID(__header) == (cap) && __pos != start) {\
__found_pos = __pos; \
+ if (prev_ptr != NULL) \
+ *(u16 *)prev_ptr = __prev_pos; \
break; \
} \
\
+ __prev_pos = __pos; \
__pos = PCI_EXT_CAP_NEXT(__header); \
} \
__found_pos; \