@@ -26,6 +26,21 @@ static const struct x86_cpu_id p2sb_cpu_ids[] = {
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
+
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
+
29
44
static int p2sb_get_devfn (unsigned int * devfn )
30
45
{
31
46
unsigned int fn = P2SB_DEVFN_DEFAULT ;
@@ -39,8 +54,16 @@ static int p2sb_get_devfn(unsigned int *devfn)
39
54
return 0 ;
40
55
}
41
56
57
+ static bool p2sb_valid_resource (struct resource * res )
58
+ {
59
+ if (res -> flags )
60
+ return true;
61
+
62
+ return false;
63
+ }
64
+
42
65
/* Copy resource from the first BAR of the device in question */
43
- static int p2sb_read_bar0 (struct pci_dev * pdev , struct resource * mem )
66
+ static void p2sb_read_bar0 (struct pci_dev * pdev , struct resource * mem )
44
67
{
45
68
struct resource * bar0 = & pdev -> resource [0 ];
46
69
@@ -56,47 +79,64 @@ static int p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)
56
79
mem -> end = bar0 -> end ;
57
80
mem -> flags = bar0 -> flags ;
58
81
mem -> desc = bar0 -> desc ;
59
-
60
- return 0 ;
61
82
}
62
83
63
- static int p2sb_scan_and_read (struct pci_bus * bus , unsigned int devfn , struct resource * mem )
84
+ static void p2sb_scan_and_cache_devfn (struct pci_bus * bus , unsigned int devfn )
64
85
{
86
+ struct p2sb_res_cache * cache = & p2sb_resources [PCI_FUNC (devfn )];
65
87
struct pci_dev * pdev ;
66
- int ret ;
67
88
68
89
pdev = pci_scan_single_device (bus , devfn );
69
90
if (!pdev )
70
- return - ENODEV ;
91
+ return ;
71
92
72
- ret = p2sb_read_bar0 (pdev , mem );
93
+ p2sb_read_bar0 (pdev , & cache -> res );
94
+ cache -> bus_dev_id = bus -> dev .id ;
73
95
74
96
pci_stop_and_remove_bus_device (pdev );
75
- return ret ;
97
+ return ;
76
98
}
77
99
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 )
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 ;
135
+ }
136
+
137
+ static int p2sb_cache_resources (void )
98
138
{
99
- struct pci_dev * pdev_p2sb ;
139
+ struct pci_bus * bus ;
100
140
unsigned int devfn_p2sb ;
101
141
u32 value = P2SBC_HIDE ;
102
142
int ret ;
@@ -106,39 +146,89 @@ int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
106
146
if (ret )
107
147
return ret ;
108
148
109
- /* if @bus is NULL, use bus 0 in domain 0 */
110
- bus = bus ?: pci_find_bus (0 , 0 );
149
+ bus = p2sb_get_bus (NULL );
150
+ if (!bus )
151
+ return - ENODEV ;
111
152
112
153
/*
113
154
* Prevent concurrent PCI bus scan from seeing the P2SB device and
114
155
* removing via sysfs while it is temporarily exposed.
115
156
*/
116
157
pci_lock_rescan_remove ();
117
158
118
- /* Unhide the P2SB device, if needed */
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
+ */
119
164
pci_bus_read_config_dword (bus , devfn_p2sb , P2SBC , & value );
120
165
if (value & P2SBC_HIDE )
121
166
pci_bus_write_config_dword (bus , devfn_p2sb , P2SBC , 0 );
122
167
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 );
168
+ ret = p2sb_scan_and_cache (bus , devfn_p2sb );
129
169
130
170
/* Hide the P2SB device, if it was hidden */
131
171
if (value & P2SBC_HIDE )
132
172
pci_bus_write_config_dword (bus , devfn_p2sb , P2SBC , P2SBC_HIDE );
133
173
134
174
pci_unlock_rescan_remove ();
135
175
136
- if (ret )
137
- return ret ;
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 ;
138
197
139
- if (mem -> flags == 0 )
198
+ bus = p2sb_get_bus (bus );
199
+ if (!bus )
140
200
return - ENODEV ;
141
201
202
+ if (!devfn ) {
203
+ ret = p2sb_get_devfn (& devfn );
204
+ if (ret )
205
+ return ret ;
206
+ }
207
+
208
+ cache = & p2sb_resources [PCI_FUNC (devfn )];
209
+ if (cache -> bus_dev_id != bus -> dev .id )
210
+ return - ENODEV ;
211
+
212
+ if (!p2sb_valid_resource (& cache -> res ))
213
+ return - ENOENT ;
214
+
215
+ memcpy (mem , & cache -> res , sizeof (* mem ));
142
216
return 0 ;
143
217
}
144
218
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