aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorrajesh.shah@intel.com <rajesh.shah@intel.com>2005-10-13 15:05:40 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 18:37:00 -0400
commit70b6091946ab486c4dab8abeb4a3fc2bf7d3e7fe (patch)
treeb61b3262529be1b03cabac951bac5cf764e2daf2 /drivers/pci/hotplug
parent1410dc1cef1e2f5e90c1fcb97041f42e0eee35b4 (diff)
[PATCH] shpchp: dont save PCI config for hotplug slots/devices
This patch eliminates saving the PCI config header for devices in hotplug capable slots. We now use the PCI core to get the specific parts of the config header as required. Signed-off-by: Rajesh Shah <rajesh.shah@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/shpchp.h1
-rw-r--r--drivers/pci/hotplug/shpchp_core.c7
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c48
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c314
4 files changed, 32 insertions, 338 deletions
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 1b345ae81ddb..5e99260987e8 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -63,7 +63,6 @@ struct pci_func {
63 u8 switch_save; 63 u8 switch_save;
64 u8 presence_save; 64 u8 presence_save;
65 u8 pwr_save; 65 u8 pwr_save;
66 u32 config_space[0x20];
67 struct pci_dev* pci_dev; 66 struct pci_dev* pci_dev;
68}; 67};
69 68
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 3132d60a79f5..5d4fc28969d0 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -424,13 +424,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
424 first_device_num = ctrl->slot_device_offset; 424 first_device_num = ctrl->slot_device_offset;
425 num_ctlr_slots = ctrl->num_slots; 425 num_ctlr_slots = ctrl->num_slots;
426 426
427 /* Store PCI Config Space for all devices on this bus */
428 rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
429 if (rc) {
430 err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
431 goto err_out_free_ctrl_bus;
432 }
433
434 ctrl->add_support = 1; 427 ctrl->add_support = 1;
435 428
436 /* Setup the slot information structures */ 429 /* Setup the slot information structures */
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 23dd61c4c66c..c55103f3cebd 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -328,21 +328,20 @@ static int slot_remove(struct pci_func * old_slot)
328/** 328/**
329 * bridge_slot_remove - Removes a node from the linked list of slots. 329 * bridge_slot_remove - Removes a node from the linked list of slots.
330 * @bridge: bridge to remove 330 * @bridge: bridge to remove
331 * @secondaryBus: secondary PCI bus number for bridge being removed
332 * @subordinateBus: subordinate PCI bus number for bridge being removed
331 * 333 *
332 * Returns 0 if successful, !0 otherwise. 334 * Returns 0 if successful, !0 otherwise.
333 */ 335 */
334static int bridge_slot_remove(struct pci_func *bridge) 336static int bridge_slot_remove(struct pci_func *bridge, u8 secondaryBus,
337 u8 subordinateBus)
335{ 338{
336 u8 subordinateBus, secondaryBus;
337 u8 tempBus; 339 u8 tempBus;
338 struct pci_func *next; 340 struct pci_func *next;
339 341
340 if (bridge == NULL) 342 if (bridge == NULL)
341 return(1); 343 return(1);
342 344
343 secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
344 subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
345
346 for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { 345 for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
347 next = shpchp_slot_list[tempBus]; 346 next = shpchp_slot_list[tempBus];
348 347
@@ -410,16 +409,23 @@ struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index)
410 return(NULL); 409 return(NULL);
411} 410}
412 411
413static int is_bridge(struct pci_func * func) 412static int is_bridge(struct pci_func *func, struct controller *ctrl)
414{ 413{
415 /* Check the header type */ 414 u8 hdr_type;
416 if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) 415 struct pci_bus *bus = ctrl->pci_dev->subordinate;
416
417 /*
418 * Note: device may have just been hot-added and not yet scanned
419 * by the pci core, so its pci_dev structure may not exist yet
420 */
421 pci_bus_read_config_byte(bus, PCI_DEVFN(func->device, func->function),
422 PCI_HEADER_TYPE, &hdr_type);
423 if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE)
417 return 1; 424 return 1;
418 else 425 else
419 return 0; 426 return 0;
420} 427}
421 428
422
423/* The following routines constitute the bulk of the 429/* The following routines constitute the bulk of the
424 hotplug controller logic 430 hotplug controller logic
425 */ 431 */
@@ -709,8 +715,6 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
709 goto err_exit; 715 goto err_exit;
710 } 716 }
711 717
712 shpchp_save_slot_config(ctrl, func);
713
714 func->status = 0; 718 func->status = 0;
715 func->switch_save = 0x10; 719 func->switch_save = 0x10;
716 func->is_a_board = 0x01; 720 func->is_a_board = 0x01;
@@ -769,10 +773,18 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
769 u8 hp_slot; 773 u8 hp_slot;
770 u32 rc; 774 u32 rc;
771 struct slot *p_slot; 775 struct slot *p_slot;
776 u8 secondary = 0, subordinate = 0;
777 int remove_bridge;
772 778
773 if (func == NULL) 779 if (func == NULL)
774 return(1); 780 return(1);
775 781
782 if ((remove_bridge = is_bridge(func, ctrl))) {
783 /* Stash away bus information before we destroy it */
784 secondary = func->pci_dev->subordinate->secondary;
785 subordinate = func->pci_dev->subordinate->subordinate;
786 }
787
776 if (shpchp_unconfigure_device(func)) 788 if (shpchp_unconfigure_device(func))
777 return(1); 789 return(1);
778 790
@@ -825,10 +837,11 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
825 837
826 if (ctrl->add_support) { 838 if (ctrl->add_support) {
827 while (func) { 839 while (func) {
828 if (is_bridge(func)) { 840 if (remove_bridge) {
829 dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 841 dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
830 func->device, func->function); 842 func->device, func->function);
831 bridge_slot_remove(func); 843 bridge_slot_remove(func, secondary,
844 subordinate);
832 } else 845 } else
833 dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, 846 dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus,
834 func->device, func->function); 847 func->device, func->function);
@@ -1185,9 +1198,12 @@ int shpchp_enable_slot (struct slot *p_slot)
1185 1198
1186 rc = board_added(func, p_slot->ctrl); 1199 rc = board_added(func, p_slot->ctrl);
1187 if (rc) { 1200 if (rc) {
1188 if (is_bridge(func)) 1201 if (is_bridge(func, p_slot->ctrl)) {
1189 bridge_slot_remove(func); 1202 u8 secondary = func->pci_dev->subordinate->secondary;
1190 else 1203 u8 subordinate =
1204 func->pci_dev->subordinate->subordinate;
1205 bridge_slot_remove(func, secondary, subordinate);
1206 } else
1191 slot_remove(func); 1207 slot_remove(func);
1192 1208
1193 /* Setup slot structure with entry for empty slot */ 1209 /* Setup slot structure with entry for empty slot */
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 6209972313f3..f51a97d7611f 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -166,317 +166,3 @@ int shpchp_unconfigure_device(struct pci_func* func)
166 return rc; 166 return rc;
167} 167}
168 168
169/* More PCI configuration routines; this time centered around hotplug controller */
170
171
172/*
173 * shpchp_save_config
174 *
175 * Reads configuration for all slots in a PCI bus and saves info.
176 *
177 * Note: For non-hot plug busses, the slot # saved is the device #
178 *
179 * returns 0 if success
180 */
181int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
182{
183 int rc;
184 u8 class_code;
185 u8 header_type;
186 u32 ID;
187 u8 secondary_bus;
188 struct pci_func *new_slot;
189 int sub_bus;
190 int FirstSupported;
191 int LastSupported;
192 int max_functions;
193 int function;
194 u8 DevError;
195 int device = 0;
196 int cloop = 0;
197 int stop_it;
198 int index;
199 int is_hot_plug = num_ctlr_slots || first_device_num;
200 struct pci_bus lpci_bus, *pci_bus;
201
202 dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
203 num_ctlr_slots, first_device_num);
204
205 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
206 pci_bus = &lpci_bus;
207
208 dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
209 num_ctlr_slots, first_device_num);
210
211 /* Decide which slots are supported */
212 if (is_hot_plug) {
213 /*********************************
214 * is_hot_plug is the slot mask
215 *********************************/
216 FirstSupported = first_device_num;
217 LastSupported = FirstSupported + num_ctlr_slots - 1;
218 } else {
219 FirstSupported = 0;
220 LastSupported = 0x1F;
221 }
222
223 dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
224 LastSupported);
225
226 /* Save PCI configuration space for all devices in supported slots */
227 pci_bus->number = busnumber;
228 for (device = FirstSupported; device <= LastSupported; device++) {
229 ID = 0xFFFFFFFF;
230 rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
231 PCI_VENDOR_ID, &ID);
232
233 if (ID != 0xFFFFFFFF) { /* device in slot */
234 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
235 0x0B, &class_code);
236 if (rc)
237 return rc;
238
239 rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
240 PCI_HEADER_TYPE, &header_type);
241 if (rc)
242 return rc;
243
244 dbg("class_code = %x, header_type = %x\n", class_code, header_type);
245
246 /* If multi-function device, set max_functions to 8 */
247 if (header_type & 0x80)
248 max_functions = 8;
249 else
250 max_functions = 1;
251
252 function = 0;
253
254 do {
255 DevError = 0;
256
257 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
258 /* Recurse the subordinate bus
259 * get the subordinate bus number
260 */
261 rc = pci_bus_read_config_byte(pci_bus,
262 PCI_DEVFN(device, function),
263 PCI_SECONDARY_BUS, &secondary_bus);
264 if (rc) {
265 return rc;
266 } else {
267 sub_bus = (int) secondary_bus;
268
269 /* Save secondary bus cfg spc with this recursive call. */
270 rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
271 if (rc)
272 return rc;
273 }
274 }
275
276 index = 0;
277 new_slot = shpchp_slot_find(busnumber, device, index++);
278
279 dbg("new_slot = %p\n", new_slot);
280
281 while (new_slot && (new_slot->function != (u8) function)) {
282 new_slot = shpchp_slot_find(busnumber, device, index++);
283 dbg("new_slot = %p\n", new_slot);
284 }
285 if (!new_slot) {
286 /* Setup slot structure. */
287 new_slot = shpchp_slot_create(busnumber);
288 dbg("new_slot = %p\n", new_slot);
289
290 if (new_slot == NULL)
291 return(1);
292 }
293
294 new_slot->bus = (u8) busnumber;
295 new_slot->device = (u8) device;
296 new_slot->function = (u8) function;
297 new_slot->is_a_board = 1;
298 new_slot->switch_save = 0x10;
299 new_slot->pwr_save = 1;
300 /* In case of unsupported board */
301 new_slot->status = DevError;
302 new_slot->pci_dev = pci_find_slot(new_slot->bus,
303 (new_slot->device << 3) | new_slot->function);
304 dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
305
306 for (cloop = 0; cloop < 0x20; cloop++) {
307 rc = pci_bus_read_config_dword(pci_bus,
308 PCI_DEVFN(device, function),
309 cloop << 2,
310 (u32 *) &(new_slot->config_space [cloop]));
311 /* dbg("new_slot->config_space[%x] = %x\n",
312 cloop, new_slot->config_space[cloop]); */
313 if (rc)
314 return rc;
315 }
316
317 function++;
318
319 stop_it = 0;
320
321 /* this loop skips to the next present function
322 * reading in Class Code and Header type.
323 */
324
325 while ((function < max_functions)&&(!stop_it)) {
326 rc = pci_bus_read_config_dword(pci_bus,
327 PCI_DEVFN(device, function),
328 PCI_VENDOR_ID, &ID);
329
330 if (ID == 0xFFFFFFFF) { /* nothing there. */
331 function++;
332 dbg("Nothing there\n");
333 } else { /* Something there */
334 rc = pci_bus_read_config_byte(pci_bus,
335 PCI_DEVFN(device, function),
336 0x0B, &class_code);
337 if (rc)
338 return rc;
339
340 rc = pci_bus_read_config_byte(pci_bus,
341 PCI_DEVFN(device, function),
342 PCI_HEADER_TYPE, &header_type);
343 if (rc)
344 return rc;
345
346 dbg("class_code = %x, header_type = %x\n",
347 class_code, header_type);
348 stop_it++;
349 }
350 }
351
352 } while (function < max_functions);
353 /* End of IF (device in slot?) */
354 } else if (is_hot_plug) {
355 /* Setup slot structure with entry for empty slot */
356 new_slot = shpchp_slot_create(busnumber);
357
358 if (new_slot == NULL) {
359 return(1);
360 }
361 dbg("new_slot = %p\n", new_slot);
362
363 new_slot->bus = (u8) busnumber;
364 new_slot->device = (u8) device;
365 new_slot->function = 0;
366 new_slot->is_a_board = 0;
367 new_slot->presence_save = 0;
368 new_slot->switch_save = 0;
369 }
370 } /* End of FOR loop */
371
372 return(0);
373}
374
375
376/*
377 * shpchp_save_slot_config
378 *
379 * Saves configuration info for all PCI devices in a given slot
380 * including subordinate busses.
381 *
382 * returns 0 if success
383 */
384int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
385{
386 int rc;
387 u8 class_code;
388 u8 header_type;
389 u32 ID;
390 u8 secondary_bus;
391 int sub_bus;
392 int max_functions;
393 int function;
394 int cloop = 0;
395 int stop_it;
396 struct pci_bus lpci_bus, *pci_bus;
397 memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
398 pci_bus = &lpci_bus;
399 pci_bus->number = new_slot->bus;
400
401 ID = 0xFFFFFFFF;
402
403 pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
404 PCI_VENDOR_ID, &ID);
405
406 if (ID != 0xFFFFFFFF) { /* device in slot */
407 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
408 0x0B, &class_code);
409
410 pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
411 PCI_HEADER_TYPE, &header_type);
412
413 if (header_type & 0x80) /* Multi-function device */
414 max_functions = 8;
415 else
416 max_functions = 1;
417
418 function = 0;
419
420 do {
421 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
422 /* Recurse the subordinate bus */
423 pci_bus_read_config_byte(pci_bus,
424 PCI_DEVFN(new_slot->device, function),
425 PCI_SECONDARY_BUS, &secondary_bus);
426
427 sub_bus = (int) secondary_bus;
428
429 /* Save the config headers for the secondary bus. */
430 rc = shpchp_save_config(ctrl, sub_bus, 0, 0);
431
432 if (rc)
433 return rc;
434
435 } /* End of IF */
436
437 new_slot->status = 0;
438
439 for (cloop = 0; cloop < 0x20; cloop++) {
440 pci_bus_read_config_dword(pci_bus,
441 PCI_DEVFN(new_slot->device, function),
442 cloop << 2,
443 (u32 *) &(new_slot->config_space [cloop]));
444 }
445
446 function++;
447
448 stop_it = 0;
449
450 /* this loop skips to the next present function
451 * reading in the Class Code and the Header type.
452 */
453
454 while ((function < max_functions) && (!stop_it)) {
455 pci_bus_read_config_dword(pci_bus,
456 PCI_DEVFN(new_slot->device, function),
457 PCI_VENDOR_ID, &ID);
458
459 if (ID == 0xFFFFFFFF) { /* nothing there. */
460 function++;
461 } else { /* Something there */
462 pci_bus_read_config_byte(pci_bus,
463 PCI_DEVFN(new_slot->device, function),
464 0x0B, &class_code);
465
466 pci_bus_read_config_byte(pci_bus,
467 PCI_DEVFN(new_slot->device, function),
468 PCI_HEADER_TYPE, &header_type);
469
470 stop_it++;
471 }
472 }
473
474 } while (function < max_functions);
475 } /* End of IF (device in slot?) */
476 else {
477 return 2;
478 }
479
480 return 0;
481}
482