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 |