diff options
author | rajesh.shah@intel.com <rajesh.shah@intel.com> | 2005-10-31 19:20:08 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-11-10 19:09:14 -0500 |
commit | ca22a5e4d70620b7f3d809e424daa5214b0aa00d (patch) | |
tree | 13f69e742475642f382bcb0350e399d14315b534 /drivers/pci/hotplug/pciehp_pci.c | |
parent | a8a2be949267cb0d1d933a92d9fb43eda4f4fe88 (diff) |
[PATCH] pciehp: remove redundant data structures
State information is currently stored in per-slot as well as
per-pci-function data structures in pciehp. There's a lot of
overlap in the information kept, and some of it is never used.
This patch consolidates the state information to per-slot and
eliminates unused data structures. The biggest change is to
eliminate the pci_func structure and the code around managing
its lists.
Signed-off-by: Rajesh Shah <rajesh.shah@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/pciehp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 349 |
1 files changed, 22 insertions, 327 deletions
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index db59a06ab0b4..1d185c1bc77a 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -101,346 +101,41 @@ int pciehp_configure_device(struct slot *p_slot) | |||
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | int pciehp_unconfigure_device(struct pci_func* func) | 104 | int pciehp_unconfigure_device(struct slot *p_slot) |
105 | { | 105 | { |
106 | int rc = 0; | 106 | int rc = 0; |
107 | int j; | 107 | int j; |
108 | struct pci_bus *pbus; | 108 | u8 bctl = 0; |
109 | 109 | ||
110 | dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, | 110 | dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, |
111 | func->device, func->function); | 111 | p_slot->device); |
112 | pbus = func->pci_dev->bus; | ||
113 | 112 | ||
114 | for (j=0; j<8 ; j++) { | 113 | for (j=0; j<8 ; j++) { |
115 | struct pci_dev* temp = pci_find_slot(func->bus, | 114 | struct pci_dev* temp = pci_find_slot(p_slot->bus, |
116 | (func->device << 3) | j); | 115 | (p_slot->device << 3) | j); |
117 | if (temp) { | 116 | if (!temp) |
118 | pci_remove_bus_device(temp); | 117 | continue; |
118 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
119 | err("Cannot remove display device %s\n", | ||
120 | pci_name(temp)); | ||
121 | continue; | ||
122 | } | ||
123 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
124 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | ||
125 | if (bctl & PCI_BRIDGE_CTL_VGA) { | ||
126 | err("Cannot remove display device %s\n", | ||
127 | pci_name(temp)); | ||
128 | continue; | ||
129 | } | ||
119 | } | 130 | } |
131 | pci_remove_bus_device(temp); | ||
120 | } | 132 | } |
121 | /* | 133 | /* |
122 | * Some PCI Express root ports require fixup after hot-plug operation. | 134 | * Some PCI Express root ports require fixup after hot-plug operation. |
123 | */ | 135 | */ |
124 | if (pcie_mch_quirk) | 136 | if (pcie_mch_quirk) |
125 | pci_fixup_device(pci_fixup_final, pbus->self); | 137 | pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev); |
126 | 138 | ||
127 | return rc; | 139 | return rc; |
128 | } | 140 | } |
129 | 141 | ||
130 | /* | ||
131 | * pciehp_save_config | ||
132 | * | ||
133 | * Reads configuration for all slots in a PCI bus and saves info. | ||
134 | * | ||
135 | * Note: For non-hot plug busses, the slot # saved is the device # | ||
136 | * | ||
137 | * returns 0 if success | ||
138 | */ | ||
139 | int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) | ||
140 | { | ||
141 | int rc; | ||
142 | u8 class_code; | ||
143 | u8 header_type; | ||
144 | u32 ID; | ||
145 | u8 secondary_bus; | ||
146 | struct pci_func *new_slot; | ||
147 | int sub_bus; | ||
148 | int max_functions; | ||
149 | int function; | ||
150 | u8 DevError; | ||
151 | int device = 0; | ||
152 | int cloop = 0; | ||
153 | int stop_it; | ||
154 | int index; | ||
155 | int is_hot_plug = num_ctlr_slots || first_device_num; | ||
156 | struct pci_bus lpci_bus, *pci_bus; | ||
157 | int FirstSupported, LastSupported; | ||
158 | |||
159 | dbg("%s: Enter\n", __FUNCTION__); | ||
160 | |||
161 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
162 | pci_bus = &lpci_bus; | ||
163 | |||
164 | dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, | ||
165 | num_ctlr_slots, first_device_num); | ||
166 | |||
167 | /* Decide which slots are supported */ | ||
168 | if (is_hot_plug) { | ||
169 | /********************************* | ||
170 | * is_hot_plug is the slot mask | ||
171 | *********************************/ | ||
172 | FirstSupported = first_device_num; | ||
173 | LastSupported = FirstSupported + num_ctlr_slots - 1; | ||
174 | } else { | ||
175 | FirstSupported = 0; | ||
176 | LastSupported = 0x1F; | ||
177 | } | ||
178 | |||
179 | dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, | ||
180 | LastSupported); | ||
181 | |||
182 | /* Save PCI configuration space for all devices in supported slots */ | ||
183 | dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number); | ||
184 | pci_bus->number = busnumber; | ||
185 | dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device); | ||
186 | for (device = FirstSupported; device <= LastSupported; device++) { | ||
187 | ID = 0xFFFFFFFF; | ||
188 | rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), | ||
189 | PCI_VENDOR_ID, &ID); | ||
190 | |||
191 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
192 | dbg("%s: ID = %x\n", __FUNCTION__, ID); | ||
193 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
194 | 0x0B, &class_code); | ||
195 | if (rc) | ||
196 | return rc; | ||
197 | |||
198 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
199 | PCI_HEADER_TYPE, &header_type); | ||
200 | if (rc) | ||
201 | return rc; | ||
202 | |||
203 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
204 | |||
205 | /* If multi-function device, set max_functions to 8 */ | ||
206 | if (header_type & 0x80) | ||
207 | max_functions = 8; | ||
208 | else | ||
209 | max_functions = 1; | ||
210 | |||
211 | function = 0; | ||
212 | |||
213 | do { | ||
214 | DevError = 0; | ||
215 | dbg("%s: In do loop\n", __FUNCTION__); | ||
216 | |||
217 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ | ||
218 | /* Recurse the subordinate bus | ||
219 | * get the subordinate bus number | ||
220 | */ | ||
221 | rc = pci_bus_read_config_byte(pci_bus, | ||
222 | PCI_DEVFN(device, function), | ||
223 | PCI_SECONDARY_BUS, &secondary_bus); | ||
224 | if (rc) { | ||
225 | return rc; | ||
226 | } else { | ||
227 | sub_bus = (int) secondary_bus; | ||
228 | |||
229 | /* Save secondary bus cfg spc with this recursive call. */ | ||
230 | rc = pciehp_save_config(ctrl, sub_bus, 0, 0); | ||
231 | if (rc) | ||
232 | return rc; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | index = 0; | ||
237 | new_slot = pciehp_slot_find(busnumber, device, index++); | ||
238 | |||
239 | dbg("%s: new_slot = %p bus %x dev %x fun %x\n", | ||
240 | __FUNCTION__, new_slot, busnumber, device, index-1); | ||
241 | |||
242 | while (new_slot && (new_slot->function != (u8) function)) { | ||
243 | new_slot = pciehp_slot_find(busnumber, device, index++); | ||
244 | dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n", | ||
245 | __FUNCTION__, new_slot, busnumber, device, index-1); | ||
246 | } | ||
247 | if (!new_slot) { | ||
248 | /* Setup slot structure. */ | ||
249 | new_slot = pciehp_slot_create(busnumber); | ||
250 | dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n", | ||
251 | __FUNCTION__, new_slot, busnumber, device, function); | ||
252 | |||
253 | if (new_slot == NULL) | ||
254 | return(1); | ||
255 | } | ||
256 | |||
257 | new_slot->bus = (u8) busnumber; | ||
258 | new_slot->device = (u8) device; | ||
259 | new_slot->function = (u8) function; | ||
260 | new_slot->is_a_board = 1; | ||
261 | new_slot->switch_save = 0x10; | ||
262 | /* In case of unsupported board */ | ||
263 | new_slot->status = DevError; | ||
264 | new_slot->pci_dev = pci_find_slot(new_slot->bus, | ||
265 | (new_slot->device << 3) | new_slot->function); | ||
266 | dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); | ||
267 | |||
268 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
269 | rc = pci_bus_read_config_dword(pci_bus, | ||
270 | PCI_DEVFN(device, function), | ||
271 | cloop << 2, | ||
272 | (u32 *) &(new_slot->config_space [cloop])); | ||
273 | /* dbg("new_slot->config_space[%x] = %x\n", | ||
274 | cloop, new_slot->config_space[cloop]); */ | ||
275 | if (rc) | ||
276 | return rc; | ||
277 | } | ||
278 | |||
279 | function++; | ||
280 | |||
281 | stop_it = 0; | ||
282 | |||
283 | /* this loop skips to the next present function | ||
284 | * reading in Class Code and Header type. | ||
285 | */ | ||
286 | |||
287 | while ((function < max_functions)&&(!stop_it)) { | ||
288 | dbg("%s: In while loop \n", __FUNCTION__); | ||
289 | rc = pci_bus_read_config_dword(pci_bus, | ||
290 | PCI_DEVFN(device, function), | ||
291 | PCI_VENDOR_ID, &ID); | ||
292 | |||
293 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
294 | function++; | ||
295 | dbg("Nothing there\n"); | ||
296 | } else { /* Something there */ | ||
297 | rc = pci_bus_read_config_byte(pci_bus, | ||
298 | PCI_DEVFN(device, function), | ||
299 | 0x0B, &class_code); | ||
300 | if (rc) | ||
301 | return rc; | ||
302 | |||
303 | rc = pci_bus_read_config_byte(pci_bus, | ||
304 | PCI_DEVFN(device, function), | ||
305 | PCI_HEADER_TYPE, &header_type); | ||
306 | if (rc) | ||
307 | return rc; | ||
308 | |||
309 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
310 | stop_it++; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | } while (function < max_functions); | ||
315 | /* End of IF (device in slot?) */ | ||
316 | } else if (is_hot_plug) { | ||
317 | /* Setup slot structure with entry for empty slot */ | ||
318 | new_slot = pciehp_slot_create(busnumber); | ||
319 | |||
320 | if (new_slot == NULL) { | ||
321 | return(1); | ||
322 | } | ||
323 | dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot, | ||
324 | new_slot->bus, new_slot->device, new_slot->function); | ||
325 | |||
326 | new_slot->bus = (u8) busnumber; | ||
327 | new_slot->device = (u8) device; | ||
328 | new_slot->function = 0; | ||
329 | new_slot->is_a_board = 0; | ||
330 | new_slot->presence_save = 0; | ||
331 | new_slot->switch_save = 0; | ||
332 | } | ||
333 | } /* End of FOR loop */ | ||
334 | |||
335 | dbg("%s: Exit\n", __FUNCTION__); | ||
336 | return(0); | ||
337 | } | ||
338 | |||
339 | |||
340 | /* | ||
341 | * pciehp_save_slot_config | ||
342 | * | ||
343 | * Saves configuration info for all PCI devices in a given slot | ||
344 | * including subordinate busses. | ||
345 | * | ||
346 | * returns 0 if success | ||
347 | */ | ||
348 | int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) | ||
349 | { | ||
350 | int rc; | ||
351 | u8 class_code; | ||
352 | u8 header_type; | ||
353 | u32 ID; | ||
354 | u8 secondary_bus; | ||
355 | int sub_bus; | ||
356 | int max_functions; | ||
357 | int function; | ||
358 | int cloop = 0; | ||
359 | int stop_it; | ||
360 | struct pci_bus lpci_bus, *pci_bus; | ||
361 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
362 | pci_bus = &lpci_bus; | ||
363 | pci_bus->number = new_slot->bus; | ||
364 | |||
365 | ID = 0xFFFFFFFF; | ||
366 | |||
367 | pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
368 | PCI_VENDOR_ID, &ID); | ||
369 | |||
370 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
371 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
372 | 0x0B, &class_code); | ||
373 | |||
374 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
375 | PCI_HEADER_TYPE, &header_type); | ||
376 | |||
377 | if (header_type & 0x80) /* Multi-function device */ | ||
378 | max_functions = 8; | ||
379 | else | ||
380 | max_functions = 1; | ||
381 | |||
382 | function = 0; | ||
383 | |||
384 | do { | ||
385 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
386 | /* Recurse the subordinate bus */ | ||
387 | pci_bus_read_config_byte(pci_bus, | ||
388 | PCI_DEVFN(new_slot->device, function), | ||
389 | PCI_SECONDARY_BUS, &secondary_bus); | ||
390 | |||
391 | sub_bus = (int) secondary_bus; | ||
392 | |||
393 | /* Save the config headers for the secondary bus. */ | ||
394 | rc = pciehp_save_config(ctrl, sub_bus, 0, 0); | ||
395 | |||
396 | if (rc) | ||
397 | return rc; | ||
398 | |||
399 | } /* End of IF */ | ||
400 | |||
401 | new_slot->status = 0; | ||
402 | |||
403 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
404 | pci_bus_read_config_dword(pci_bus, | ||
405 | PCI_DEVFN(new_slot->device, function), | ||
406 | cloop << 2, | ||
407 | (u32 *) &(new_slot->config_space [cloop])); | ||
408 | } | ||
409 | |||
410 | function++; | ||
411 | |||
412 | stop_it = 0; | ||
413 | |||
414 | /* this loop skips to the next present function | ||
415 | * reading in the Class Code and the Header type. | ||
416 | */ | ||
417 | |||
418 | while ((function < max_functions) && (!stop_it)) { | ||
419 | pci_bus_read_config_dword(pci_bus, | ||
420 | PCI_DEVFN(new_slot->device, function), | ||
421 | PCI_VENDOR_ID, &ID); | ||
422 | |||
423 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
424 | function++; | ||
425 | } else { /* Something there */ | ||
426 | pci_bus_read_config_byte(pci_bus, | ||
427 | PCI_DEVFN(new_slot->device, function), | ||
428 | 0x0B, &class_code); | ||
429 | |||
430 | pci_bus_read_config_byte(pci_bus, | ||
431 | PCI_DEVFN(new_slot->device, function), | ||
432 | PCI_HEADER_TYPE, &header_type); | ||
433 | |||
434 | stop_it++; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | } while (function < max_functions); | ||
439 | } /* End of IF (device in slot?) */ | ||
440 | else { | ||
441 | return 2; | ||
442 | } | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||