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