1
1. Refactor capability search into common macros.
1
1. Introduce generic bus config read helper function.
2
2. Refactor capability search functions to eliminate code duplication.
2
2. Clean up __pci_find_next_cap_ttl() readability.
3
2. DWC/CDNS use common PCI host bridge macros for finding the
3
3. Refactor capability search into common macros.
4
4. DWC/CDNS use common PCI host bridge macros for finding the
4
capabilities.
5
capabilities.
5
3. Use cdns_pcie_find_*capability to avoid hardcode.
6
5. Use cdns_pcie_find_*capability to avoid hardcode.
7
8
Changes since v8:
9
- Split patch.
10
- The patch commit message were modified.
11
- Other patches(4/6, 5/6, 6/6) are unchanged.
6
12
7
Changes since v7:
13
Changes since v7:
8
- Patch 2/5 and 3/5 compilation error resolved.
14
- Patch 2/5 and 3/5 compilation error resolved.
9
- Other patches are unchanged.
15
- Other patches are unchanged.
10
16
...
...
29
- Other patches are not modified.
35
- Other patches are not modified.
30
36
31
Changes since v2:
37
Changes since v2:
32
- Add and split into a series of patches.
38
- Add and split into a series of patches.
33
39
34
Hans Zhang (5):
40
Hans Zhang (6):
41
PCI: Introduce generic bus config read helper function
42
PCI: Clean up __pci_find_next_cap_ttl() readability
35
PCI: Refactor capability search into common macros
43
PCI: Refactor capability search into common macros
36
PCI: Refactor capability search functions to eliminate code
37
duplication
38
PCI: dwc: Use common PCI host bridge APIs for finding the capabilities
44
PCI: dwc: Use common PCI host bridge APIs for finding the capabilities
39
PCI: cadence: Use common PCI host bridge APIs for finding the
45
PCI: cadence: Use common PCI host bridge APIs for finding the
40
capabilities
46
capabilities
41
PCI: cadence: Use cdns_pcie_find_*capability to avoid hardcode.
47
PCI: cadence: Use cdns_pcie_find_*capability to avoid hardcode.
42
48
49
drivers/pci/access.c | 17 ++++
43
.../pci/controller/cadence/pcie-cadence-ep.c | 40 +++++----
50
.../pci/controller/cadence/pcie-cadence-ep.c | 40 +++++----
44
drivers/pci/controller/cadence/pcie-cadence.c | 28 +++++++
51
drivers/pci/controller/cadence/pcie-cadence.c | 28 ++++++
45
drivers/pci/controller/cadence/pcie-cadence.h | 18 +++--
52
drivers/pci/controller/cadence/pcie-cadence.h | 18 ++--
46
drivers/pci/controller/dwc/pcie-designware.c | 72 ++---------------
53
drivers/pci/controller/dwc/pcie-designware.c | 72 ++-------------
47
drivers/pci/pci.c | 80 ++++++------------
54
drivers/pci/pci.c | 68 ++------------
48
drivers/pci/pci.h | 81 +++++++++++++++++++
55
drivers/pci/pci.h | 88 +++++++++++++++++++
49
include/uapi/linux/pci_regs.h | 2 +
56
include/uapi/linux/pci_regs.h | 2 +
50
7 files changed, 177 insertions(+), 144 deletions(-)
57
8 files changed, 187 insertions(+), 146 deletions(-)
51
58
52
59
53
base-commit: acb4f33713b9f6cadb6143f211714c343465411c
60
base-commit: a24588245776dafc227243a01bfbeb8a59bafba9
54
--
61
--
55
2.25.1
62
2.25.1
diff view generated by jsdifflib
New patch
1
The primary PCI config space accessors are tied to the size of the read
2
(byte/word/dword). Upcoming refactoring of PCI capability discovery logic
3
requires passing a config accessor function that must be able to perform
4
read with different sizes.
1
5
6
Add any size config space read accessor pci_bus_read_config() to allow
7
giving it as the config space accessor to the upcoming PCI capability
8
discovery macro.
9
10
Reconstructs the PCI function discovery logic to prepare for unified
11
configuration of access modes. No function changes are intended.
12
13
Signed-off-by: Hans Zhang <18255117159@163.com>
14
---
15
Changes since v8:
16
- The new split is patch 1/6.
17
- The patch commit message were modified.
18
---
19
drivers/pci/access.c | 17 +++++++++++++++++
20
drivers/pci/pci.h | 2 ++
21
2 files changed, 19 insertions(+)
22
23
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/drivers/pci/access.c
26
+++ b/drivers/pci/access.c
27
@@ -XXX,XX +XXX,XX @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
28
EXPORT_SYMBOL(pci_bus_write_config_word);
29
EXPORT_SYMBOL(pci_bus_write_config_dword);
30
31
+int pci_bus_read_config(void *priv, unsigned int devfn, int where, u32 size,
32
+            u32 *val)
33
+{
34
+    struct pci_bus *bus = priv;
35
+    int ret;
36
+
37
+    if (size == 1)
38
+        ret = pci_bus_read_config_byte(bus, devfn, where, (u8 *)val);
39
+    else if (size == 2)
40
+        ret = pci_bus_read_config_word(bus, devfn, where, (u16 *)val);
41
+    else
42
+        ret = pci_bus_read_config_dword(bus, devfn, where, val);
43
+
44
+    return ret;
45
+}
46
+EXPORT_SYMBOL_GPL(pci_bus_read_config);
47
+
48
int pci_generic_config_read(struct pci_bus *bus, unsigned int devfn,
49
             int where, int size, u32 *val)
50
{
51
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/drivers/pci/pci.h
54
+++ b/drivers/pci/pci.h
55
@@ -XXX,XX +XXX,XX @@ extern bool pci_early_dump;
56
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
57
bool pcie_cap_has_lnkctl2(const struct pci_dev *dev);
58
bool pcie_cap_has_rtctl(const struct pci_dev *dev);
59
+int pci_bus_read_config(void *priv, unsigned int devfn, int where, u32 size,
60
+            u32 *val);
61
62
/* Functions internal to the PCI core code */
63
64
--
65
2.25.1
diff view generated by jsdifflib
1
Introduce PCI_FIND_NEXT_CAP_TTL and PCI_FIND_NEXT_EXT_CAPABILITY macros
1
Refactor the __pci_find_next_cap_ttl() to improve code clarity:
2
to consolidate duplicate PCI capability search logic found throughout the
2
- Replace magic number 0x40 with PCI_STD_HEADER_SIZEOF.
3
driver tree. This refactoring:
3
- Use ALIGN_DOWN() for position alignment instead of manual bitmask.
4
- Extract PCI capability fields via FIELD_GET() with standardized masks.
5
- Add necessary headers (linux/align.h, uapi/linux/pci_regs.h).
4
6
5
1. Eliminates code duplication in capability scanning routines
7
The changes are purely non-functional cleanups, ensuring behavior remains
6
2. Provides a standardized, maintainable implementation
8
identical to the original implementation.
7
3. Reduces error-prone copy-paste implementations
8
4. Maintains identical functionality to existing code
9
10
The macros abstract the low-level capability register scanning while
11
preserving the existing PCI configuration space access patterns. They will
12
enable future conversions of multiple capability search implementations
13
across various drivers (e.g., PCI core, controller drivers) to use
14
this centralized logic.
15
9
16
Signed-off-by: Hans Zhang <18255117159@163.com>
10
Signed-off-by: Hans Zhang <18255117159@163.com>
17
---
11
---
18
drivers/pci/pci.h | 81 +++++++++++++++++++++++++++++++++++
12
Changes since v8:
19
include/uapi/linux/pci_regs.h | 2 +
13
- Split into patch 1/6, patch 2/6.
20
2 files changed, 83 insertions(+)
14
- The patch commit message were modified.
15
---
16
drivers/pci/pci.c | 10 ++++++----
17
include/uapi/linux/pci_regs.h | 2 ++
18
2 files changed, 8 insertions(+), 4 deletions(-)
21
19
22
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
20
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
23
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
24
--- a/drivers/pci/pci.h
22
--- a/drivers/pci/pci.c
25
+++ b/drivers/pci/pci.h
23
+++ b/drivers/pci/pci.c
26
@@ -XXX,XX +XXX,XX @@ bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
24
@@ -XXX,XX +XXX,XX @@
27
bool pcie_cap_has_lnkctl2(const struct pci_dev *dev);
25
*/
28
bool pcie_cap_has_rtctl(const struct pci_dev *dev);
26
29
27
#include <linux/acpi.h>
30
+/* Standard Capability finder */
28
+#include <linux/align.h>
31
+/**
29
#include <linux/kernel.h>
32
+ * PCI_FIND_NEXT_CAP_TTL - Find a PCI standard capability
30
#include <linux/delay.h>
33
+ * @read_cfg: Function pointer for reading PCI config space
31
#include <linux/dmi.h>
34
+ * @start: Starting position to begin search
32
@@ -XXX,XX +XXX,XX @@
35
+ * @cap: Capability ID to find
33
#include <asm/dma.h>
36
+ * @args: Arguments to pass to read_cfg function
34
#include <linux/aer.h>
37
+ *
35
#include <linux/bitfield.h>
38
+ * Iterates through the capability list in PCI config space to find
36
+#include <uapi/linux/pci_regs.h>
39
+ * the specified capability. Implements TTL (time-to-live) protection
37
#include "pci.h"
40
+ * against infinite loops.
38
41
+ *
39
DEFINE_MUTEX(pci_slot_mutex);
42
+ * Returns: Position of the capability if found, 0 otherwise.
40
@@ -XXX,XX +XXX,XX @@ static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
43
+ */
41
    pci_bus_read_config_byte(bus, devfn, pos, &pos);
44
+#define PCI_FIND_NEXT_CAP_TTL(read_cfg, start, cap, args...)        \
42
45
+({                                    \
43
    while ((*ttl)--) {
46
+    u8 __pos = (start);                        \
44
-        if (pos < 0x40)
47
+    int __ttl = PCI_FIND_CAP_TTL;                    \
45
+        if (pos < PCI_STD_HEADER_SIZEOF)
48
+    u16 __ent;                            \
46
            break;
49
+    u8 __found_pos = 0;                        \
47
-        pos &= ~3;
50
+    u8 __id;                            \
48
+        pos = ALIGN_DOWN(pos, 4);
51
+                                    \
49
        pci_bus_read_config_word(bus, devfn, pos, &ent);
52
+    read_cfg(args, __pos, 1, (u32 *)&__pos);            \
50
53
+                                    \
51
-        id = ent & 0xff;
54
+    while (__ttl--) {                        \
52
+        id = FIELD_GET(PCI_CAP_ID_MASK, ent);
55
+        if (__pos < PCI_STD_HEADER_SIZEOF)            \
53
        if (id == 0xff)
56
+            break;                        \
54
            break;
57
+        __pos = ALIGN_DOWN(__pos, 4);                \
55
        if (id == cap)
58
+        read_cfg(args, __pos, 2, (u32 *)&__ent);        \
56
            return pos;
59
+        __id = FIELD_GET(PCI_CAP_ID_MASK, __ent);        \
57
-        pos = (ent >> 8);
60
+        if (__id == 0xff)                    \
58
+        pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, ent);
61
+            break;                        \
59
    }
62
+        if (__id == (cap)) {                    \
60
    return 0;
63
+            __found_pos = __pos;                \
61
}
64
+            break;                        \
65
+        }                            \
66
+        __pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, __ent);    \
67
+    }                                \
68
+    __found_pos;                            \
69
+})
70
+
71
+/* Extended Capability finder */
72
+/**
73
+ * PCI_FIND_NEXT_EXT_CAPABILITY - Find a PCI extended capability
74
+ * @read_cfg: Function pointer for reading PCI config space
75
+ * @start: Starting position to begin search (0 for initial search)
76
+ * @cap: Extended capability ID to find
77
+ * @args: Arguments to pass to read_cfg function
78
+ *
79
+ * Searches the extended capability space in PCI config registers
80
+ * for the specified capability. Implements TTL protection against
81
+ * infinite loops using a calculated maximum search count.
82
+ *
83
+ * Returns: Position of the capability if found, 0 otherwise.
84
+ */
85
+#define PCI_FIND_NEXT_EXT_CAPABILITY(read_cfg, start, cap, args...)        \
86
+({                                        \
87
+    u16 __pos = (start) ?: PCI_CFG_SPACE_SIZE;                \
88
+    u16 __found_pos = 0;                            \
89
+    int __ttl, __ret;                            \
90
+    u32 __header;                                \
91
+                                        \
92
+    __ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;        \
93
+    while (__ttl-- > 0 && __pos >= PCI_CFG_SPACE_SIZE) {            \
94
+        __ret = read_cfg(args, __pos, 4, &__header);            \
95
+        if (__ret != PCIBIOS_SUCCESSFUL)                \
96
+            break;                            \
97
+                                        \
98
+        if (__header == 0)                        \
99
+            break;                            \
100
+                                        \
101
+        if (PCI_EXT_CAP_ID(__header) == (cap) && __pos != start) {    \
102
+            __found_pos = __pos;                    \
103
+            break;                            \
104
+        }                                \
105
+                                        \
106
+        __pos = PCI_EXT_CAP_NEXT(__header);                \
107
+    }                                    \
108
+    __found_pos;                                \
109
+})
110
+
111
/* Functions internal to the PCI core code */
112
113
#ifdef CONFIG_DMI
114
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
62
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
115
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
116
--- a/include/uapi/linux/pci_regs.h
64
--- a/include/uapi/linux/pci_regs.h
117
+++ b/include/uapi/linux/pci_regs.h
65
+++ b/include/uapi/linux/pci_regs.h
118
@@ -XXX,XX +XXX,XX @@
66
@@ -XXX,XX +XXX,XX @@
...
...
diff view generated by jsdifflib
1
Refactor the PCI capability and extended capability search functions
1
The PCI Capability search functionality is duplicated across the PCI core
2
by consolidating common code patterns into reusable macros
2
and several controller drivers. The core's current implementation requires
3
(PCI_FIND_NEXT_CAP_TTL and PCI_FIND_NEXT_EXT_CAPABILITY). The main
3
fully initialized PCI device and bus structures, which prevents controller
4
changes include:
4
drivers from using it during early initialization phases before these
5
5
structures are available.
6
1. Introducing a unified config space read helper (__pci_bus_read_config).
6
7
2. Removing duplicate search logic from __pci_find_next_cap_ttl and
7
Move the Capability search logic into a header-based macro that accepts a
8
pci_find_next_ext_capability.
8
config space accessor function as an argument. This enables controller
9
3. Implementing consistent capability discovery using the new macros.
9
drivers to perform Capability discovery using their early access
10
4. Simplifying HyperTransport capability lookup by leveraging the
10
mechanisms prior to full device initialization while sharing the
11
refactored code.
11
Capability search code.
12
12
13
The refactoring maintains existing functionality while reducing code
13
Convert the existing PCI core Capability search implementation to use this
14
duplication and improving maintainability. By centralizing the search
14
new macro.
15
logic, we achieve better code consistency and make future updates easier.
15
16
16
The macros now implement, parameterized by the config access method. The
17
This change has been verified to maintain backward compatibility with
17
PCI core functions are converted to utilize these macros with the standard
18
existing capability discovery patterns through thorough testing of PCI
18
pci_bus_read_config accessors. Controller drivers can later use the same
19
device enumeration and capability probing.
19
macros with their early access mechanisms while maintaining the existing
20
protection against infinite loops through preserved TTL checks.
21
22
The ttl parameter was originally an additional safeguard to prevent
23
infinite loops in corrupted config space. However, the
24
PCI_FIND_NEXT_CAP_TTL macro already enforces a TTL limit internally.
25
Removing redundant ttl handling simplifies the interface while maintaining
26
the safety guarantee. This aligns with the macro's design intent of
27
encapsulating TTL management.
20
28
21
Signed-off-by: Hans Zhang <18255117159@163.com>
29
Signed-off-by: Hans Zhang <18255117159@163.com>
22
---
30
---
23
Changes since v7:
31
Changes since v8:
24
https://lore.kernel.org/linux-pci/20250402042020.48681-3-18255117159@163.com
32
- The patch commit message were modified.
25
26
- Resolve compilation errors.
27
---
33
---
28
drivers/pci/pci.c | 80 ++++++++++++++---------------------------------
34
drivers/pci/pci.c | 70 +++++---------------------------------
29
1 file changed, 23 insertions(+), 57 deletions(-)
35
drivers/pci/pci.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++
36
2 files changed, 95 insertions(+), 61 deletions(-)
30
37
31
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
38
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
32
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
33
--- a/drivers/pci/pci.c
40
--- a/drivers/pci/pci.c
34
+++ b/drivers/pci/pci.c
41
+++ b/drivers/pci/pci.c
42
@@ -XXX,XX +XXX,XX @@
43
*/
44
45
#include <linux/acpi.h>
46
-#include <linux/align.h>
47
#include <linux/kernel.h>
48
#include <linux/delay.h>
49
#include <linux/dmi.h>
50
@@ -XXX,XX +XXX,XX @@
51
#include <asm/dma.h>
52
#include <linux/aer.h>
53
#include <linux/bitfield.h>
54
-#include <uapi/linux/pci_regs.h>
55
#include "pci.h"
56
57
DEFINE_MUTEX(pci_slot_mutex);
35
@@ -XXX,XX +XXX,XX @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
58
@@ -XXX,XX +XXX,XX @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
36
    return 1;
59
}
37
}
60
38
61
static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
39
-static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
40
-                 u8 pos, int cap, int *ttl)
62
-                 u8 pos, int cap, int *ttl)
41
+static int __pci_bus_read_config(void *priv, unsigned int devfn, int where,
63
+                 u8 pos, int cap)
42
+                 u32 size, u32 *val)
43
{
64
{
44
-    u8 id;
65
-    u8 id;
45
-    u16 ent;
66
-    u16 ent;
46
+    struct pci_bus *bus = priv;
67
-
47
+    int ret;
48
49
-    pci_bus_read_config_byte(bus, devfn, pos, &pos);
68
-    pci_bus_read_config_byte(bus, devfn, pos, &pos);
50
+    if (size == 1)
69
-
51
+        ret = pci_bus_read_config_byte(bus, devfn, where, (u8 *)val);
52
+    else if (size == 2)
53
+        ret = pci_bus_read_config_word(bus, devfn, where, (u16 *)val);
54
+    else
55
+        ret = pci_bus_read_config_dword(bus, devfn, where, val);
56
57
-    while ((*ttl)--) {
70
-    while ((*ttl)--) {
58
-        if (pos < 0x40)
71
-        if (pos < PCI_STD_HEADER_SIZEOF)
59
-            break;
72
-            break;
60
-        pos &= ~3;
73
-        pos = ALIGN_DOWN(pos, 4);
61
-        pci_bus_read_config_word(bus, devfn, pos, &ent);
74
-        pci_bus_read_config_word(bus, devfn, pos, &ent);
62
+    return ret;
75
-
63
+}
76
-        id = FIELD_GET(PCI_CAP_ID_MASK, ent);
64
65
-        id = ent & 0xff;
66
-        if (id == 0xff)
77
-        if (id == 0xff)
67
-            break;
78
-            break;
68
-        if (id == cap)
79
-        if (id == cap)
69
-            return pos;
80
-            return pos;
70
-        pos = (ent >> 8);
81
-        pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, ent);
71
-    }
82
-    }
72
-    return 0;
83
-    return 0;
73
+static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
84
+    return PCI_FIND_NEXT_CAP_TTL(pci_bus_read_config, pos, cap, bus,
74
+                 u8 pos, int cap)
75
+{
76
+    return PCI_FIND_NEXT_CAP_TTL(__pci_bus_read_config, pos, cap, bus,
77
+                 devfn);
85
+                 devfn);
78
}
86
}
79
87
80
static u8 __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
88
static u8 __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
81
             u8 pos, int cap)
89
             u8 pos, int cap)
...
...
125
-        if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
133
-        if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
126
-            break;
134
-            break;
127
-    }
135
-    }
128
-
136
-
129
-    return 0;
137
-    return 0;
130
+    return PCI_FIND_NEXT_EXT_CAPABILITY(__pci_bus_read_config, start, cap,
138
+    return PCI_FIND_NEXT_EXT_CAPABILITY(pci_bus_read_config, start, cap,
131
+                     dev->bus, dev->devfn);
139
+                     dev->bus, dev->devfn);
132
}
140
}
133
EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
141
EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
134
142
135
@@ -XXX,XX +XXX,XX @@ EXPORT_SYMBOL_GPL(pci_get_dsn);
143
@@ -XXX,XX +XXX,XX @@ EXPORT_SYMBOL_GPL(pci_get_dsn);
...
...
157
-                     PCI_CAP_ID_HT, &ttl);
165
-                     PCI_CAP_ID_HT, &ttl);
158
+                     PCI_CAP_ID_HT);
166
+                     PCI_CAP_ID_HT);
159
    }
167
    }
160
168
161
    return 0;
169
    return 0;
170
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
171
index XXXXXXX..XXXXXXX 100644
172
--- a/drivers/pci/pci.h
173
+++ b/drivers/pci/pci.h
174
@@ -XXX,XX +XXX,XX @@
175
#ifndef DRIVERS_PCI_H
176
#define DRIVERS_PCI_H
177
178
+#include <linux/align.h>
179
#include <linux/pci.h>
180
+#include <uapi/linux/pci_regs.h>
181
182
struct pcie_tlp_log;
183
184
@@ -XXX,XX +XXX,XX @@ bool pcie_cap_has_rtctl(const struct pci_dev *dev);
185
int pci_bus_read_config(void *priv, unsigned int devfn, int where, u32 size,
186
            u32 *val);
187
188
+/* Standard Capability finder */
189
+/**
190
+ * PCI_FIND_NEXT_CAP_TTL - Find a PCI standard capability
191
+ * @read_cfg: Function pointer for reading PCI config space
192
+ * @start: Starting position to begin search
193
+ * @cap: Capability ID to find
194
+ * @args: Arguments to pass to read_cfg function
195
+ *
196
+ * Iterates through the capability list in PCI config space to find
197
+ * the specified capability. Implements TTL (time-to-live) protection
198
+ * against infinite loops.
199
+ *
200
+ * Returns: Position of the capability if found, 0 otherwise.
201
+ */
202
+#define PCI_FIND_NEXT_CAP_TTL(read_cfg, start, cap, args...)        \
203
+({                                    \
204
+    int __ttl = PCI_FIND_CAP_TTL;                    \
205
+    u8 __id, __found_pos = 0;                    \
206
+    u8 __pos = (start);                        \
207
+    u16 __ent;                            \
208
+                                    \
209
+    read_cfg(args, __pos, 1, (u32 *)&__pos);            \
210
+                                    \
211
+    while (__ttl--) {                        \
212
+        if (__pos < PCI_STD_HEADER_SIZEOF)            \
213
+            break;                        \
214
+                                    \
215
+        __pos = ALIGN_DOWN(__pos, 4);                \
216
+        read_cfg(args, __pos, 2, (u32 *)&__ent);        \
217
+                                    \
218
+        __id = FIELD_GET(PCI_CAP_ID_MASK, __ent);        \
219
+        if (__id == 0xff)                    \
220
+            break;                        \
221
+                                    \
222
+        if (__id == (cap)) {                    \
223
+            __found_pos = __pos;                \
224
+            break;                        \
225
+        }                            \
226
+                                    \
227
+        __pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, __ent);    \
228
+    }                                \
229
+    __found_pos;                            \
230
+})
231
+
232
+/* Extended Capability finder */
233
+/**
234
+ * PCI_FIND_NEXT_EXT_CAPABILITY - Find a PCI extended capability
235
+ * @read_cfg: Function pointer for reading PCI config space
236
+ * @start: Starting position to begin search (0 for initial search)
237
+ * @cap: Extended capability ID to find
238
+ * @args: Arguments to pass to read_cfg function
239
+ *
240
+ * Searches the extended capability space in PCI config registers
241
+ * for the specified capability. Implements TTL protection against
242
+ * infinite loops using a calculated maximum search count.
243
+ *
244
+ * Returns: Position of the capability if found, 0 otherwise.
245
+ */
246
+#define PCI_FIND_NEXT_EXT_CAPABILITY(read_cfg, start, cap, args...)        \
247
+({                                        \
248
+    u16 __pos = (start) ?: PCI_CFG_SPACE_SIZE;                \
249
+    u16 __found_pos = 0;                            \
250
+    int __ttl, __ret;                            \
251
+    u32 __header;                                \
252
+                                        \
253
+    __ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;        \
254
+    while (__ttl-- > 0 && __pos >= PCI_CFG_SPACE_SIZE) {            \
255
+        __ret = read_cfg(args, __pos, 4, &__header);            \
256
+        if (__ret != PCIBIOS_SUCCESSFUL)                \
257
+            break;                            \
258
+                                        \
259
+        if (__header == 0)                        \
260
+            break;                            \
261
+                                        \
262
+        if (PCI_EXT_CAP_ID(__header) == (cap) && __pos != start) {    \
263
+            __found_pos = __pos;                    \
264
+            break;                            \
265
+        }                                \
266
+                                        \
267
+        __pos = PCI_EXT_CAP_NEXT(__header);                \
268
+    }                                    \
269
+    __found_pos;                                \
270
+})
271
+
272
/* Functions internal to the PCI core code */
273
274
#ifdef CONFIG_DMI
162
--
275
--
163
2.25.1
276
2.25.1
diff view generated by jsdifflib
1
Use the PCI core is now exposing generic macros for the host bridges to
1
Use the PCI core is now exposing generic macros for the host bridges to
2
search for the PCIe capabilities, make use of them in the DWC driver.
2
search for the PCIe capabilities, make use of them in the DWC driver.
3
3
4
Signed-off-by: Hans Zhang <18255117159@163.com>
4
Signed-off-by: Hans Zhang <18255117159@163.com>
5
---
5
---
6
Changes since v8:
7
- None
8
6
Changes since v7:
9
Changes since v7:
7
https://lore.kernel.org/linux-pci/20250402042020.48681-4-18255117159@163.com/
10
- Resolve compilation errors.
8
11
9
- Resolve compilation errors.
12
Changes since v6:
13
https://lore.kernel.org/linux-pci/20250323164852.430546-3-18255117159@163.com/
14
15
- The patch commit message were modified.
16
17
Changes since v5:
18
https://lore.kernel.org/linux-pci/20250321163803.391056-3-18255117159@163.com/
19
20
- Kconfig add "select PCI_HOST_HELPERS"
10
---
21
---
11
drivers/pci/controller/dwc/pcie-designware.c | 72 ++------------------
22
drivers/pci/controller/dwc/pcie-designware.c | 72 ++------------------
12
1 file changed, 7 insertions(+), 65 deletions(-)
23
1 file changed, 7 insertions(+), 65 deletions(-)
13
24
14
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
25
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
...
...
37
-    reg = dw_pcie_readw_dbi(pci, cap_ptr);
48
-    reg = dw_pcie_readw_dbi(pci, cap_ptr);
38
-    cap_id = (reg & 0x00ff);
49
-    cap_id = (reg & 0x00ff);
39
-
50
-
40
-    if (cap_id > PCI_CAP_ID_MAX)
51
-    if (cap_id > PCI_CAP_ID_MAX)
41
-        return 0;
52
-        return 0;
42
+    struct dw_pcie *pcie = priv;
53
+    struct dw_pcie *pci = priv;
43
54
44
-    if (cap_id == cap)
55
-    if (cap_id == cap)
45
-        return cap_ptr;
56
-        return cap_ptr;
46
+    *val = dw_pcie_read_dbi(pcie, where, size);
57
+    *val = dw_pcie_read_dbi(pci, where, size);
47
58
48
-    next_cap_ptr = (reg & 0xff00) >> 8;
59
-    next_cap_ptr = (reg & 0xff00) >> 8;
49
-    return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
60
-    return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
50
+    return PCIBIOS_SUCCESSFUL;
61
+    return PCIBIOS_SUCCESSFUL;
51
}
62
}
...
...
diff view generated by jsdifflib
1
Use the PCI core is now exposing generic macros for the host bridges to
1
Use the PCI core is now exposing generic macros for the host bridges to
2
search for the PCIe capabilities, make use of them in the CDNS driver.
2
search for the PCIe capabilities, make use of them in the CDNS driver.
3
3
4
Signed-off-by: Hans Zhang <18255117159@163.com>
4
Signed-off-by: Hans Zhang <18255117159@163.com>
5
---
5
---
6
Changes since v8:
7
- None
8
9
Changes since v7:
10
- Resolve compilation errors.
11
6
Changes since v6:
12
Changes since v6:
7
https://lore.kernel.org/linux-pci/20250323164852.430546-4-18255117159@163.com/
13
https://lore.kernel.org/linux-pci/20250323164852.430546-4-18255117159@163.com/
8
14
9
- The patch commit message were modified.
15
- The patch commit message were modified.
10
16
...
...
diff view generated by jsdifflib
...
...
4
4
5
This avoids hardcoding the offsets in the driver.
5
This avoids hardcoding the offsets in the driver.
6
6
7
Signed-off-by: Hans Zhang <18255117159@163.com>
7
Signed-off-by: Hans Zhang <18255117159@163.com>
8
---
8
---
9
Changes since v5~v7:
9
Changes since v5~v8:
10
10
11
- None
11
- None
12
12
13
Changes since v4:
13
Changes since v4:
14
https://lore.kernel.org/linux-pci/20250321101710.371480-5-18255117159@163.com/
14
https://lore.kernel.org/linux-pci/20250321101710.371480-5-18255117159@163.com/
...
...
diff view generated by jsdifflib