History

Merge tag 'platform-drivers-x86-v6.7-7' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver fix from Ilpo Järvinen: "Unfortunately the P2SB deadlock fix broke some older HW and we need some time to figure out the best way to fix the issue so reverting the deadlock fix for now" * tag 'platform-drivers-x86-v6.7-7' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: Revert "platform/x86: p2sb: Allow p2sb_bar() calls during PCI device probe"

Linus Torvalds committed 2 years ago

Commit 5eff55d2 parents 08bd31e b20712e1 file · +41 −131Browse files

Unified · Split

drivers/platform/x86/p2sb.c+41−131
@@ -26,21 +26,6 @@ static const struct x86_cpu_id p2sb_cpu_ids[] = { · 25 unmodified lines
26 {}26 {}
27};27};
28 28
29/*
30 * Cache BAR0 of P2SB device functions 0 to 7.
31 * TODO: The constant 8 is the number of functions that PCI specification
32 * defines. Same definitions exist tree-wide. Unify this definition and
33 * the other definitions then move to include/uapi/linux/pci.h.
34 */
35#define NR_P2SB_RES_CACHE 8
36
37struct p2sb_res_cache {
38 u32 bus_dev_id;
39 struct resource res;
40};
41
42static struct p2sb_res_cache p2sb_resources[NR_P2SB_RES_CACHE];
43
44static int p2sb_get_devfn(unsigned int *devfn)29static int p2sb_get_devfn(unsigned int *devfn)
45{30{
46 unsigned int fn = P2SB_DEVFN_DEFAULT;31 unsigned int fn = P2SB_DEVFN_DEFAULT;
@@ -54,16 +39,8 @@ static int p2sb_get_devfn(unsigned int *devfn) · 7 unmodified lines
54 return 0;39 return 0;
55}40}
56 41
57static bool p2sb_valid_resource(struct resource *res)
58{
59 if (res->flags)
60 return true;
61
62 return false;
63}
64
65/* Copy resource from the first BAR of the device in question */42/* Copy resource from the first BAR of the device in question */
66static void p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)43static int p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)
67{44{
68 struct resource *bar0 = &pdev->resource[0];45 struct resource *bar0 = &pdev->resource[0];
69 46
@@ -79,64 +56,47 @@ static void p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem) · 9 unmodified lines
79 mem->end = bar0->end;56 mem->end = bar0->end;
80 mem->flags = bar0->flags;57 mem->flags = bar0->flags;
81 mem->desc = bar0->desc;58 mem->desc = bar0->desc;
59
60 return 0;
82}61}
83 62
84static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn)63static int p2sb_scan_and_read(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
85{64{
86 struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)];
87 struct pci_dev *pdev;65 struct pci_dev *pdev;
66 int ret;
88 67
89 pdev = pci_scan_single_device(bus, devfn);68 pdev = pci_scan_single_device(bus, devfn);
90 if (!pdev)69 if (!pdev)
91 return;70 return -ENODEV;
92 71
93 p2sb_read_bar0(pdev, &cache->res);72 ret = p2sb_read_bar0(pdev, mem);
94 cache->bus_dev_id = bus->dev.id;
95 73
96 pci_stop_and_remove_bus_device(pdev);74 pci_stop_and_remove_bus_device(pdev);
97 return;75 return ret;
98}
99
100static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn)
101{
102 unsigned int slot, fn;
103
104 if (PCI_FUNC(devfn) == 0) {
105 /*
106 * When function number of the P2SB device is zero, scan it and
107 * other function numbers, and if devices are available, cache
108 * their BAR0s.
109 */
110 slot = PCI_SLOT(devfn);
111 for (fn = 0; fn < NR_P2SB_RES_CACHE; fn++)
112 p2sb_scan_and_cache_devfn(bus, PCI_DEVFN(slot, fn));
113 } else {
114 /* Scan the P2SB device and cache its BAR0 */
115 p2sb_scan_and_cache_devfn(bus, devfn);
116 }
117
118 if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res))
119 return -ENOENT;
120
121 return 0;
122}
123
124static struct pci_bus *p2sb_get_bus(struct pci_bus *bus)
125{
126 static struct pci_bus *p2sb_bus;
127
128 bus = bus ?: p2sb_bus;
129 if (bus)
130 return bus;
131
132 /* Assume P2SB is on the bus 0 in domain 0 */
133 p2sb_bus = pci_find_bus(0, 0);
134 return p2sb_bus;
135}76}
136 77
137static int p2sb_cache_resources(void)78/**
79 * p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR
80 * @bus: PCI bus to communicate with
81 * @devfn: PCI slot and function to communicate with
82 * @mem: memory resource to be filled in
83 *
84 * The BIOS prevents the P2SB device from being enumerated by the PCI
85 * subsystem, so we need to unhide and hide it back to lookup the BAR.
86 *
87 * if @bus is NULL, the bus 0 in domain 0 will be used.
88 * If @devfn is 0, it will be replaced by devfn of the P2SB device.
89 *
90 * Caller must provide a valid pointer to @mem.
91 *
92 * Locking is handled by pci_rescan_remove_lock mutex.
93 *
94 * Return:
95 * 0 on success or appropriate errno value on error.
96 */
97int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
138{98{
139 struct pci_bus *bus;99 struct pci_dev *pdev_p2sb;
140 unsigned int devfn_p2sb;100 unsigned int devfn_p2sb;
141 u32 value = P2SBC_HIDE;101 u32 value = P2SBC_HIDE;
142 int ret;102 int ret;
@@ -146,9 +106,8 @@ static int p2sb_cache_resources(void) · 3 unmodified lines
146 if (ret)106 if (ret)
147 return ret;107 return ret;
148 108
149 bus = p2sb_get_bus(NULL);109 /* if @bus is NULL, use bus 0 in domain 0 */
150 if (!bus)110 bus = bus ?: pci_find_bus(0, 0);
151 return -ENODEV;
152 111
153 /*112 /*
154 * Prevent concurrent PCI bus scan from seeing the P2SB device and113 * Prevent concurrent PCI bus scan from seeing the P2SB device and
@@ -156,16 +115,17 @@ static int p2sb_cache_resources(void) · 1 unmodified line
156 */115 */
157 pci_lock_rescan_remove();116 pci_lock_rescan_remove();
158 117
159 /*118 /* Unhide the P2SB device, if needed */
160 * The BIOS prevents the P2SB device from being enumerated by the PCI
161 * subsystem, so we need to unhide and hide it back to lookup the BAR.
162 * Unhide the P2SB device here, if needed.
163 */
164 pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);119 pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);
165 if (value & P2SBC_HIDE)120 if (value & P2SBC_HIDE)
166 pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0);121 pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0);
167 122
168 ret = p2sb_scan_and_cache(bus, devfn_p2sb);123 pdev_p2sb = pci_scan_single_device(bus, devfn_p2sb);
124 if (devfn)
125 ret = p2sb_scan_and_read(bus, devfn, mem);
126 else
127 ret = p2sb_read_bar0(pdev_p2sb, mem);
128 pci_stop_and_remove_bus_device(pdev_p2sb);
169 129
170 /* Hide the P2SB device, if it was hidden */130 /* Hide the P2SB device, if it was hidden */
171 if (value & P2SBC_HIDE)131 if (value & P2SBC_HIDE)
@@ -173,62 +133,12 @@ static int p2sb_cache_resources(void) · 1 unmodified line
173 133
174 pci_unlock_rescan_remove();134 pci_unlock_rescan_remove();
175 135
176 return ret;136 if (ret)
177}137 return ret;
178
179/**
180 * p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR
181 * @bus: PCI bus to communicate with
182 * @devfn: PCI slot and function to communicate with
183 * @mem: memory resource to be filled in
184 *
185 * If @bus is NULL, the bus 0 in domain 0 will be used.
186 * If @devfn is 0, it will be replaced by devfn of the P2SB device.
187 *
188 * Caller must provide a valid pointer to @mem.
189 *
190 * Return:
191 * 0 on success or appropriate errno value on error.
192 */
193int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
194{
195 struct p2sb_res_cache *cache;
196 int ret;
197
198 bus = p2sb_get_bus(bus);
199 if (!bus)
200 return -ENODEV;
201
202 if (!devfn) {
203 ret = p2sb_get_devfn(&devfn);
204 if (ret)
205 return ret;
206 }
207 138
208 cache = &p2sb_resources[PCI_FUNC(devfn)];139 if (mem->flags == 0)
209 if (cache->bus_dev_id != bus->dev.id)
210 return -ENODEV;140 return -ENODEV;
211 141
212 if (!p2sb_valid_resource(&cache->res))
213 return -ENOENT;
214
215 memcpy(mem, &cache->res, sizeof(*mem));
216 return 0;142 return 0;
217}143}
218EXPORT_SYMBOL_GPL(p2sb_bar);144EXPORT_SYMBOL_GPL(p2sb_bar);
219
220static int __init p2sb_fs_init(void)
221{
222 p2sb_cache_resources();
223 return 0;
224}
225
226/*
227 * pci_rescan_remove_lock to avoid access to unhidden P2SB devices can
228 * not be locked in sysfs pci bus rescan path because of deadlock. To
229 * avoid the deadlock, access to P2SB devices with the lock at an early
230 * step in kernel initialization and cache required resources. This
231 * should happen after subsys_initcall which initializes PCI subsystem
232 * and before device_initcall which requires P2SB resources.
233 */
234fs_initcall(p2sb_fs_init);