Skip to content

Commit 5eff55d

Browse files
committed
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"
2 parents 08bd31e + b20712e commit 5eff55d

File tree

1 file changed

+41
-131
lines changed

1 file changed

+41
-131
lines changed

drivers/platform/x86/p2sb.c

Lines changed: 41 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,6 @@ static const struct x86_cpu_id p2sb_cpu_ids[] = {
2626
{}
2727
};
2828

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-
37-
struct p2sb_res_cache {
38-
u32 bus_dev_id;
39-
struct resource res;
40-
};
41-
42-
static struct p2sb_res_cache p2sb_resources[NR_P2SB_RES_CACHE];
43-
4429
static int p2sb_get_devfn(unsigned int *devfn)
4530
{
4631
unsigned int fn = P2SB_DEVFN_DEFAULT;
@@ -54,16 +39,8 @@ static int p2sb_get_devfn(unsigned int *devfn)
5439
return 0;
5540
}
5641

57-
static bool p2sb_valid_resource(struct resource *res)
58-
{
59-
if (res->flags)
60-
return true;
61-
62-
return false;
63-
}
64-
6542
/* Copy resource from the first BAR of the device in question */
66-
static void p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)
43+
static int p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)
6744
{
6845
struct resource *bar0 = &pdev->resource[0];
6946

@@ -79,64 +56,47 @@ static void p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)
7956
mem->end = bar0->end;
8057
mem->flags = bar0->flags;
8158
mem->desc = bar0->desc;
59+
60+
return 0;
8261
}
8362

84-
static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn)
63+
static int p2sb_scan_and_read(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
8564
{
86-
struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)];
8765
struct pci_dev *pdev;
66+
int ret;
8867

8968
pdev = pci_scan_single_device(bus, devfn);
9069
if (!pdev)
91-
return;
70+
return -ENODEV;
9271

93-
p2sb_read_bar0(pdev, &cache->res);
94-
cache->bus_dev_id = bus->dev.id;
72+
ret = p2sb_read_bar0(pdev, mem);
9573

9674
pci_stop_and_remove_bus_device(pdev);
97-
return;
98-
}
99-
100-
static 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-
124-
static 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;
75+
return ret;
13576
}
13677

137-
static 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+
*/
97+
int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
13898
{
139-
struct pci_bus *bus;
99+
struct pci_dev *pdev_p2sb;
140100
unsigned int devfn_p2sb;
141101
u32 value = P2SBC_HIDE;
142102
int ret;
@@ -146,89 +106,39 @@ static int p2sb_cache_resources(void)
146106
if (ret)
147107
return ret;
148108

149-
bus = p2sb_get_bus(NULL);
150-
if (!bus)
151-
return -ENODEV;
109+
/* if @bus is NULL, use bus 0 in domain 0 */
110+
bus = bus ?: pci_find_bus(0, 0);
152111

153112
/*
154113
* Prevent concurrent PCI bus scan from seeing the P2SB device and
155114
* removing via sysfs while it is temporarily exposed.
156115
*/
157116
pci_lock_rescan_remove();
158117

159-
/*
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-
*/
118+
/* Unhide the P2SB device, if needed */
164119
pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);
165120
if (value & P2SBC_HIDE)
166121
pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0);
167122

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);
169129

170130
/* Hide the P2SB device, if it was hidden */
171131
if (value & P2SBC_HIDE)
172132
pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, P2SBC_HIDE);
173133

174134
pci_unlock_rescan_remove();
175135

176-
return ret;
177-
}
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-
*/
193-
int 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-
}
136+
if (ret)
137+
return ret;
207138

208-
cache = &p2sb_resources[PCI_FUNC(devfn)];
209-
if (cache->bus_dev_id != bus->dev.id)
139+
if (mem->flags == 0)
210140
return -ENODEV;
211141

212-
if (!p2sb_valid_resource(&cache->res))
213-
return -ENOENT;
214-
215-
memcpy(mem, &cache->res, sizeof(*mem));
216142
return 0;
217143
}
218144
EXPORT_SYMBOL_GPL(p2sb_bar);
219-
220-
static 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-
*/
234-
fs_initcall(p2sb_fs_init);

0 commit comments

Comments
 (0)